简体   繁体   中英

Entity Framework foreign key relationship returns no data

I have two tables order and order_lines . They both have primary/foreign key relationship. However, when I try to retrieve data, then I don't see any data from my navigational property.

[Table("order")]
public class order : BaseModel
{
    public order()
    {
        this.OrderLines = new List<order_lines>();
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id { get; set; }
    public double? total { get; set; }

    public List<order_lines> OrderLines { get; set; }
}

[Table("order_lines")]
public class order_lines : BaseModel
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id { get; set; }
    public int? ordernum { get; set; }
    [MaxLength(1000)]
    public string sku { get; set; }

    [ForeignKey("id")]
    public order Order { get; set; }
}

And I am using the Linq query shown below to obtain data. I would like to see OrderLines property populated, but it returns 0 count.

var data = (from o in Context.order
            select o).ToList();

The cause of your problem is that you forgot to define a property for your foreign key. Because of the foreign key attribute, I guess it will be in your order_lines table.

I noticed that you deviate from the entity framework code first conventions . Are there good reasons for this? These deviations make your code bigger, more difficult to understand, more difficult to maintain and more error prone if changed by others.

The major deviation is that you omitted a property for the foreign key. Another one is that you defined your one-to-many relation as a List<order_lines] instead of an ICollection<order_lines] . Are you sure that MyOrder.Order_Lines[4] has a defined meaning?

Besides, are you certain that the result of your query is a real List? Could it be that internally the database query would return something that is similar to a List, but in fact is something else, for instance an array? Do you really want to limit yourself and users of your code to a List?

Furthermore your one-to-many references OrderLines and Order are not declared virtual. They will not be columns in your tables.

Finally you don't stick to your own naming conventions nor to the ones commonly used for C#. Class order_lines has a plural identifier, class order has a singular identifier. order_lines is in small letters, while your reference to the collection of order_lines starts with a capital. Besides OrderLines is suddenly without an underscore

Although this is allowed, and your compiler won't complain, these deviations require several attributes or fluent API to make it work. Besides it will make if more difficult for others to read your code and understand the relations between your tables.

So my advise would be: stick to the conventions, only deviate if you really need to. Not because 'you forgot'.

If you stick to the conventions, a lot of code and most of the attributes you use are not needed.

class Order : BaseModel
{
    public int Id { get; set; }

    // every Order has zero or more OrderLines
    public virtual ICollection <OrderLines> OrderLines { get; set; }

    public double? Total { get; set; }
}

public class OrderLines : BaseModel
{
    public int id { get; set; }

    // every OrderLine belongs to exactly one Order, using foreign key
    public int OrderId {get; set;}
    public virtual Order Order { get; set; }

    public int? Ordernum { get; set; }
    [MaxLength(1000)]
    public string Sku { get; set; }
}

Because I stuck to the conventions this is all that entity framework needs to understand your one-to-many relation. It knows which properties are your primary keys and which ones are the foreign keys. The only attribute that is left is the maximum length for Sku

Note that I changed your List to an ICollection. Furthermore I removed the constructor. In queries your constructor would create a list that would immediately be replaced by the result from the query: what a waste!

Finally I used proper names for identifiers.

Introducing a new order with several OrderLines would be done as follows:

var addedOrder = myDbContext.Orders.Add(new Order()
{
     Total = calculatedTotal, // or null

     OrderLines = new OrderLines[]
     {
          new OrderLine() {Sku = ...; ...},
          new OrderLine() {Sku = ...; ...},
          new OrderLine() {Sku = ...; ...},
     },
});

Note that in this example I created an array of OrderLines . I defined an ICollection. Therefore I could also have used a ListOrderLine> , or (let's do crazy) use the values of a Dictionary<int, OrderLine> , or the ToList() of some query.

I could also have added the OrderLines like this:

var addedOrder = myDbContext.Orders.Add(new Order()
{
     OrderLines = new List<OrderLine>(),
});
addedOrder.OrderLines.Add(new OrderLine() {...};

Or:

var addedOrder = myDbContext.OrderLines.Add(new OrderLine()
{
     Order = addedOrder,
     ...
});

All made possible because the references between Orders and OrderLines are declared as virtual and as ICollection.

You set you foreign-key to your pk. I think it should be "orderId" not "id".

[ForeignKey("orderId")] // Select you column with you FKey
public order Order { get; set; }

And your List needs to refer to the Property. Add the attribute [InverseProperty("Order")] and Change the type to ICollection:

[InverseProperty("Order")] // Select the property-name of the Other class
public ICollection<order_lines> OrderLines { get; set; }

if you are not using the standard naming conventions, then you MUST do the following within your context to solve this problem.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<Orders>()
            .HasKey(e => e.CaregiverCode)
            .HasMany(e => e.OrderLines)
            .WithOptional(e => e.Orders)
            .HasForeignKey(e => e.ordernum);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM