实体框架相关数据外键

时间:2018-12-12 19:24:52

标签: c# entity-framework

我有一个仅由其他实体的外键组成的实体。 我的简化类如下:

 DeliverNote
     Adress add1 {get; set;}
     Adress add2 {get; set;} 

我可以自己加载地址,但是我不能加载DeliveryNote,因为我默认情况下EF不会加载相关数据。 所以我看到了解决方案,主要是使用context.notes.Include(dn => dn.Adresses),但是我只是想不通如何告诉便笺或地址类如何彼此关联。基本上,当我键入“ dn”时。什么都没有显示。

我看到的最简单,可能可行的解决方案是来自Microsoft。在此页面https://docs.microsoft.com/de-de/ef/core/querying/related-data的github中,您可以看到Blog和Post类。在我看来,Post类似乎有缺陷,为什么Post必须知道它所在的Blog?在代码优先解决方案中,这也会使数据库混乱。如果同一篇文章要发布在多个博客上怎么办?

大多数解决方案似乎也都是某种形式的列表,我没有列表,只有简单的单个对象。我认为是1-1关系。

2 个答案:

答案 0 :(得分:2)

如果您将模型定义为:

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#模型中的属性。

答案 1 :(得分:1)

因此,您有一个数据库,该数据库具有一个function urlGenerator (key, value) { let temp = '(?<='+`${key}`+'=)[^&]+' let reg = new RegExp(temp,'g'); console.log(reg); var url = "www.domain.com/?id=10&name=xxx&dob=2018-12-13"; // change the value for given key return url.replace(reg, value); } result = urlGenerator('id', 15); console.log(result); result = urlGenerator('name', 'yyy'); console.log(result); result = urlGenerator('dob', '2018-10-20'); console.log(result);表和一个Addresses表。每个DeliveryNotes都有两个指向DeliveryNote的外键:一个Addresses和一个From(您将其称为addr1和addr2)

如果您遵循entity framework code first conventions,将会看到以下内容:

To
  

在实体框架中,表的列由非虚拟属性表示。虚拟属性表示表之间的关系。

请注意,ICollection和FromAddress / ToAddress是虚拟的,因此不是列中的列。如果需要,您可以将其排除在课堂之外。但是,如果您具有这些虚拟属性,则不必自己进行(Group)Joins。

  

我可以自己加载地址,但是我不能加载DeliveryNote,因为默认情况下EF不会加载相关数据...我

由此很难检测到您想要哪种查询。

数据库查询的最慢部分之一是将所选数据从DBMS传输到本地进程。因此,将传输的数据减到最少是明智的。

如果使用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;} } ,则将传输完整的对象,包括外键和不需要的所有属性。如果您有学校和学生的数据库,那么每个学生都将拥有他所就读学校的外键。如果您使用Include要求学校的ID为4的“有1000名学生的学校”,则您不想将外键SchoolId传送1000次,因为您已经知道它将具有值4

  

在实体框架中,仅当您要更改/更新获取的项目时才使用包括,否则使用选择

给出一堆DeliveryNotes,给我一些AddressDetails:

Include

实体框架知道一对多关系,并将为您执行适当的联接。

给出一些地址,给我一些收到的送达通知

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,
            ...
       },
   });

实体框架知道一对多关系,并将为您进行适当的组联接。

  

如果您具有一对多关系,并且想要“带有许多子项目的项目”,请从一侧开始使用虚拟ICollection。如果您想要带有其所属项目的子项目,请从多面开始,并在一侧使用虚拟属性