繁体   English   中英

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

[英]Entity Framework foreign key relationship returns no data

我有两个表orderorder_lines 他们都有主/外键关系。 但是,当我尝试检索数据时,我没有看到来自我的导航属性的任何数据。

[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; }
}

我正在使用下面显示的Linq查询来获取数据。 我想看到OrderLines属性已填充,但它返回0计数。

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

问题的原因是您忘记为外键定义属性。 由于外键属性,我猜它会在你的order_lines表中。

我注意到你偏离了实体框架代码的第一个约定 这有充分的理由吗? 这些偏差会使您的代码变得更大,更难以理解,更难以维护,并且如果被其他人更改则更容易出错。

主要的偏差是您省略了外键的属性。 另一个是您将一对多关系定义为List<order_lines]而不是ICollection<order_lines] 你确定MyOrder.Order_Lines[4]有明确的含义吗?

此外,您确定您的查询结果是真正的列表吗? 可能是内部数据库查询会返回类似于List的东西,但实际上是其他东西,例如数组? 您真的想将自己和代码用户限制为List吗?

此外,您的一对多引用OrderLinesOrder未声明为虚拟。 它们不是表格中的列。

最后,您不会遵循自己的命名约定,也不会遵循C#常用的约定。 order_lines具有复数标识符,类order具有单数标识符。 order_lines是小写字母,而您对order_lines集合的引用以大写字母开头。 除了OrderLines突然没有下划线

虽然这是允许的,并且您的编译器不会抱怨,但这些偏差需要几个属性或流畅的API才能使其工作。 除此之外,如果其他人更难以阅读您的代码并理解您的表之间的关系。

所以我的建议是:坚持惯例,只有你真的需要偏离。 不是因为'你忘了'。

如果遵守惯例,则不需要使用大量代码和大多数属性。

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; }
}

因为我坚持惯例,所以实体框架需要了解你的一对多关系。 它知道哪些属性是您的主键,哪些是外键。 剩下的唯一属性是Sku的最大长度

请注意,我将您的列表更改为ICollection。 此外,我删除了构造函数。 在查询中,构造函数将创建一个列表,该列表将立即被查询的结果替换:多么浪费!

最后,我使用了正确的名称标识符。

引入包含多个OrderLines的新订单将按如下方式完成:

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

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

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

我也可以像这样添加OrderLines:

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

要么:

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

所有这些都成为可能,因为Orders和OrderLines之间的引用被声明为virtual和ICollection。

你为你的PK设置了外键。 我认为它应该是“orderId”而不是“id”。

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

您的列表需要引用该属性。 添加attribute [InverseProperty("Order")]并将类型更改为ICollection:

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

如果您没有使用标准命名约定,那么您必须在上下文中执行以下操作来解决此问题。

    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