[英]Entity Framework Related Data Foreign Keys
我有一个只包含其他实体的外键的实体。 我的简化类看起来像这样:
DeliverNote
Adress add1 {get; set;}
Adress add2 {get; set;}
我可以自己加载地址,但是我无法加载DeliveryNote,因为我认为EF默认情况下不会加载相关数据。 所以我看到了解决方案,主要是context.notes.Include(dn => dn.Adresses),但我无法弄清楚我是如何告诉笔记或地址类它们是如何相互关联的。 当我输入“dn”时基本上。 没有出现。
我看到的最简单,可能正在工作的解决方案来自微软。 在本页的https://docs.microsoft.com/de-de/ef/core/querying/related-data的github中,您可以看到Blog和Post类。 对我来说,Post类看起来有缺陷,为什么帖子必须知道它所在的博客? 这将在代码优先解决方案中弄乱数据库。 如果同一篇文章将在几个博客中发布怎么办?
大多数解决方案似乎也是某种列表,我没有列表,只是简单的单个对象。 我认为1-1关系。
如果将模型定义为:
public class DeliverNote {
public int Id { get; set; }
public Adress addr1 { get; set; }
public Adress addr2 { get; set; }
}
public class Adress {
public int Id { get; set; }
}
然后你可以打电话:
context.notes.Include(dn => dn.addr1).Include(dn => dn.addr2);
其中将包括相关数据。
您的模型没有为addr1或addr2定义外键,因此EF Core将为您创建阴影属性,即表中存在但不作为c#模型中的属性的列。
所以你有一个包含Addresses
表和DeliveryNotes
表的数据库。 每个DeliveryNote
都有两个Addresses
外键:一个From
和一个To
(你称之为addr1和addr2)
如果你遵循实体框架代码的第一个约定 ,你会有这样的事情:
class Address
{
public int Id {get; set;}
... // other properties
// every Address has sent zero or more delivery Notes (one-to-many)
public virtual ICollection<DeliveryNote> SentNotes {get; set};
// every Address has received zero or more delivery Notes (one-to-many)
public virtual ICollection<DeliveryNote> ReceivedNotes {get; set};
}
class DeliveryNote
{
public int Id {get; set;}
... // other properties
// every DeliveryNote comes from an Address, using foreign key
public int FromId {get; set;}
public virtual Address FromAddress {get; set;}
// every DeliverNote is sent to an Address, using foreign key:
public int ToId {get; set;}
public virtual Address ToAddress {get; set;}
}
在实体框架中,表的列由非虚拟属性表示。 虚拟属性表示表之间的关系。
请注意,ICollection和FromAddress / ToAddress是虚拟的,因此不是列中的列。 如果需要,您可以将它们排除在课堂之外。 但是,如果您拥有这些虚拟属性,则不必自己执行(组)连接。
我可以自己加载地址就好了,但我无法加载DeliveryNote,因为默认情况下EF不会加载相关数据...我
从中可以轻松地检测出您想要的查询类型。
数据库查询的一个较慢部分是将所选数据从DBMS传输到本地进程。 因此,最小化传输的数据是明智的。
如果使用Include
,则传输完整对象,包括外键和您不需要的所有属性。 如果您有一个包含学校和学生的数据库,那么每个学生都将拥有他所在学校的外键。 如果您使用Include要求“Id 1000他的学生”学校,使用Include,您不想将外键SchoolId运送1000次,因为您已经知道它将具有价值4
在实体框架中,如果要更改/更新已获取的项目,则仅使用“包含”,否则使用“选择”
给出一堆DeliveryNotes,给我一些AddressDetails:
IQueryable<DeliveryNote> deliveryNotes = dbContext.DeliveryNotes
.Where (deliveryNote => ...) // probably something with Id, or Date, or subject
.Select(deliveryNote => new
{
// select only the delivery note properties you actually plan to use
Subject = deliveryNote.Subject,
DeliveryDate = deliveryNote.DeliveryDate,
...
From = new
{
// select only the From properties you plan to use
Id = deliveryNote.FromAddress.Id,
Name = deliveryNote.FromAddress.Name,
Address = deliveryNote.FromAddress.Address,
...
}
To = new
{
// again: only properties you'll use
Name = deliveryNote.ToAddress.Name,
...
},
});
实体框架知道一对多关系,并将为您执行正确的连接。
鉴于一堆地址给了我一些他们收到的DeliveryNotes
var query = dbContext.Addresses
.Where(address => address.City == "New York" && ...)
.Select(address => new
{
// only properties you plan to use
Id = address.Id,
Name = address.Name,
ReceivedNotes = address.ReceivedNotes
.Where(note => note.DeliveryDate.Year == 2018)
.Select(note => new
{
// only properties you plan to use:
Title = note.Title,
...
// no need for this, you know it equals Id
// AddressId = note.FromId,
}),
});
实体框架知道一对多关系,并将为您做适当的groupjoin。
如果您有一对多的关系并且您想要“具有多个子项目的项目”,请从单侧开始并使用虚拟ICollection。 如果您希望子项目包含它所属的项目,请从多方面开始,并将虚拟属性用于单侧
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.