简体   繁体   English

实体框架外键关系不返回任何数据

[英]Entity Framework foreign key relationship returns no data

I have two tables order and order_lines . 我有两个表orderorder_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. 我正在使用下面显示的Linq查询来获取数据。 I would like to see OrderLines property populated, but it returns 0 count. 我想看到OrderLines属性已填充,但它返回0计数。

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. 由于外键属性,我猜它会在你的order_lines表中。

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] . 另一个是您将一对多关系定义为List<order_lines]而不是ICollection<order_lines] Are you sure that MyOrder.Order_Lines[4] has a defined meaning? 你确定MyOrder.Order_Lines[4]有明确的含义吗?

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? 可能是内部数据库查询会返回类似于List的东西,但实际上是其他东西,例如数组? Do you really want to limit yourself and users of your code to a List? 您真的想将自己和代码用户限制为List吗?

Furthermore your one-to-many references OrderLines and Order are not declared virtual. 此外,您的一对多引用OrderLinesOrder未声明为虚拟。 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#. 最后,您不会遵循自己的命名约定,也不会遵循C#常用的约定。 Class order_lines has a plural identifier, class order has a singular identifier. order_lines具有复数标识符,类order具有单数标识符。 order_lines is in small letters, while your reference to the collection of order_lines starts with a capital. order_lines是小写字母,而您对order_lines集合的引用以大写字母开头。 Besides OrderLines is suddenly without an underscore 除了OrderLines突然没有下划线

Although this is allowed, and your compiler won't complain, these deviations require several attributes or fluent API to make it work. 虽然这是允许的,并且您的编译器不会抱怨,但这些偏差需要几个属性或流畅的API才能使其工作。 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 剩下的唯一属性是Sku的最大长度

Note that I changed your List to an ICollection. 请注意,我将您的列表更改为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: 引入包含多个OrderLines的新订单将按如下方式完成:

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 . 请注意,在此示例中,我创建了一个OrderLines array I defined an ICollection. 我定义了一个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. 因此我也可以使用ListOrderLine> ,或者(让我们疯狂)使用某些查询的Dictionary<int, OrderLine>ToList()的值。

I could also have added the OrderLines like this: 我也可以像这样添加OrderLines:

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. 所有这些都成为可能,因为Orders和OrderLines之间的引用被声明为virtual和ICollection。

You set you foreign-key to your pk. 你为你的PK设置了外键。 I think it should be "orderId" not "id". 我认为它应该是“orderId”而不是“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: 添加attribute [InverseProperty("Order")]并将类型更改为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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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