1

I'm building Backend for Mobile Application with ASP.NET MVC Framework. I have two Objects:

public class CarLogItem : EntityData
{
    public CarLogItem(): base()
    {
        Time = DateTime.Now;
    }

    public DateTime Time { get; set; }

    public int RPM { get; set; }
    public int Speed { get; set; }  
    public int RunTime { get; set; }
    public int Distance { get; set; }
    public int Throttle { get; set; }

    [ForeignKey("Trip")]
    public String Trip_id { get; set; }

    // Navigation property
    public TripItem Trip { get; set; }
}

and

public class TripItem : EntityData
{
    public TripItem() : base()
    {
        UserId = User.GetUserSid();
        StartTime = DateTime.Now;
        logItems = new List<CarLogItem>();
    }
    public string UserId { get; set; }

    public List<CarLogItem> logItems {get;set;}
    public DateTime StartTime { get; set; }
}

and I have controller, which add new CarLogItem to database.

public class CarLogItemController : TableController<CarLogItem>
{
    // POST tables/CarLogItem
    public async Task<IHttpActionResult> PostCarLogItem(CarLogItem item)
    {
        var lastItem = db.CarLogItems.OrderByDescending(x => x.Time).FirstOrDefault();
        //lastItem = (Query().Where(logitem => true).OrderBy(logitem => logitem.Time)).Last();

        //checking if lastItem.Trip isn't null because
        //  I have entities with Trip field is null, but all of them should have it.
        if (lastItem != null && lastItem.Trip != null && item.RunTime > lastItem.RunTime)
        {
            item.Trip = lastItem.Trip;
        }

        //In order to test adding of new TripItem entity to database
        //  I compare item.RunTime with 120, so it always true
        else if (lastItem == null || item.RunTime < 120) // < lastItem.RunTime)
        {
            var newTrip = new TripItem();
            item.Trip = newTrip;
        }
        else
        {
            throw new ArgumentException();
        }

        CarLogItem current = await InsertAsync(item);

        return CreatedAtRoute("Tables", new { id = current.Id }, current);
    }
}

When I'm trying to add new CarLogItem with Trip = null it's ok, but when Trip is particular object it fails with following Exception:

The entity submitted was invalid: Validation error on property 'Id': The Id field is required

How properly to add new CarLogItem with nested TripItem?

5
  • It's apparent that you need to set the Id property, but you've given no code that demonstrates anything has an Id property. Commented Apr 25, 2016 at 14:56
  • What is TripItem primary key? I cannot see it in your model. Commented Apr 25, 2016 at 14:57
  • Both my entities inherits Id property from EntityData Commented Apr 25, 2016 at 15:03
  • @МихаилБабушкин could you show EntityData class? Commented Apr 25, 2016 at 15:04
  • @AndreiM from Microsoft documentation Id property marked with [CompilerGeneratedAttribute], so I suppose it's do all magic by itself, like it do for CarLogItem's Id property Commented Apr 25, 2016 at 15:10

2 Answers 2

1

I think that you need to populate the Id property on your TripItem, e.g.

var newTrip = new TripItem(){ Id = Guid.NewGuid() }
Sign up to request clarification or add additional context in comments.

3 Comments

Isn't it setting in base Constructor of EntityData? I'm not setting Id for CarLogItem and after inserting CarLogItem current = await InsertAsync(item); it returns CarLogItem with Id
I added Id initialization to TripItem Constructor Id = Guid.NewGuid().ToString(); and now it works. But I still don't understand why MVC generate Id for CarlogItem automatically but don't do that for TripItem
It could be the way the DB is set up and whether it autogenerates and ID value
0

You need a primary key field in every entity class, like Id or CarLogItemId (ClassName + "Id"). Or just have a property with [Key] attribute:

[Key]
public string/int/Guid/any-db-supported-type MyProp { get; set; }

Entity Framework relies on every entity having a key value that it uses for tracking entities. One of the conventions that code first depends on is how it implies which property is the key in each of the code first classes. That convention is to look for a property named “Id” or one that combines the class name and “Id”, such as “BlogId”. The property will map to a primary key column in the database.

Please see this for more details.


I also suspect this to be a problem:

public Lazy<CarLogItem> logItems { get; set; }

You don't have to mark navigation property as Lazy<>. It is already lazy (unless you have configuration that disables lazy loading). Please try to remove Lazy<> and see if it works this way.

1 Comment

Yes, actually it should be List<>. I was just trying to use Lazy, but it didn't make a sense. It's same exception in both cases. I edited post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.