繁体   English   中英

实体框架相关数据外键

[英]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.

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