[英]Entity Framework foreign key relationship returns no data
我有两个表order
和order_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吗?
此外,您的一对多引用OrderLines
和Order
未声明为虚拟。 它们不是表格中的列。
最后,您不会遵循自己的命名约定,也不会遵循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.