实体框架参考属性 [英] Entity Framework reference property

查看:29
本文介绍了实体框架参考属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Entity Framework 6.

I am working with Entity Framework 6.

我正在上2个班级:

public partial class StateProvince
{

     public StateProvince()
    {
        Addresses = new HashSet<Address>();
    }

    public int StateProvinceID { get; set; }

    public string StateProvinceCode { get; set; }

    public string CountryRegionCode { get; set; }

    public bool IsOnlyStateProvinceFlag { get; set; }

    public string Name { get; set; }

    public int TerritoryID { get; set; }

    public Guid rowguid { get; set; }

    public DateTime ModifiedDate { get; set; }

    public ICollection<Address> Addresses { get; set; }

    public CountryRegion CountryRegion { get; set; }

}

public partial class CountryRegion
{
    public CountryRegion()
    {
        StateProvinces = new HashSet<StateProvinceTlb>();
    }

    public string CountryRegionCode { get; set; }

    public string Name { get; set; }

    public DateTime ModifiedDate { get; set; }

    public virtual ICollection<StateProvince> StateProvinces { get; set;}
}

我希望能够运行一个查询,该查询将返回StateProvince的列表,但还要包含CountryRegion中的名称.这个想法是,在编辑屏幕上,用户将选择或编辑CountryRegionCode,但是Name将显示在其旁边的不可编辑字段中,仅供参考.

I would like to be able to run a query that would return a list of StateProvince, but also include the name from CountryRegion. The idea is that on an edit screen, the user will select, or edit the CountryRegionCode, but the Name will display beside it in a none editable field just for reference.

我尝试将属性作为非映射字段添加到StateProvince并在CountryRegion上引用该属性,如下所示:

I tried adding property as a none mapped field to StateProvince and referencing the property on CountryRegion, like below:

    [NotMapped]
    public string CountryName
    {
        get{ return CountryRegion.Name;}
    }

但这是一个问题,必须加载CountryRegion才能使它正常工作,而我的目标是不必加载整个CountryRegion对象.

but the problem with this is the CountryRegion has to be loaded in order for that to work, and my goal is to not have to load the entire CountryRegion object.

我也试图像这样在查询中设置它:

I've also tried to set it in my query like this:

            List<StateProvince> statP = context.StateProvinces.Select(s => new StateProvince() {s, CountryName = context.CountryRegions.Where(x => x.CountryRegionCode == s.CountryRegionCode).Select(x => x.Name).FirstOrDefault() }).ToList();

但这不起作用,因为返回的对象由StateProvince对象和单独的CountryName属性组成.

but this doesn't work because the object returned is comprised of a StateProvince object and a separate CountryName property.

我甚至尝试过分别设置每个字段,例如:

I've even tried setting each of the fields individually like:

            List<StateProvince> statP = context.StateProvinces.Select(s => new StateProvince() { Name = s.Name, TerritoryID = s.TerritoryID, rowguid = s.rowguid, ModifiedDate = s.ModifiedDate, Addresses=s.Addresses, CountryRegion=s.CountryRegion, CountryName = context.CountryRegions.Where(x => x.CountryRegionCode == s.CountryRegionCode).Select(x => x.Name).FirstOrDefault() }).ToList();

但这再次导致整个CountryRegion对象加载,并且如果我将那些属性留在外面,则会引发异常.此外,对于较大的实体,这将很难维护.

But this again causes the entire CountryRegion object to load, and if I leave those properties out, an exception is thrown. Also, for larger entities this will be hard to maintain.

TLDR;的版本:实体框架中是否有一种方法可以将一个类映射到一个表,但是在该类上有一个属性,而该属性引用了另一个表上的属性,而不必检索子表上的所有内容?

The TLDR; version of this: Is there a way in Entity Frameworks to have a class mapped to one table, but have a property on that class that references a property on another table without having to retrieve everything on the child table?

我已经搜索了很多,但实际上找不到涵盖这种特定情况的任何内容.我对Entity Framework不太熟悉,感觉好像缺少了一些明显的东西.任何帮助将不胜感激!

I've searched and searched and can't really find much covering this specific kinda of scenario. I'm fairly new to Entity Framework, and I feel like I'm missing something obvious. Any help would be greatly appreciated!!

解决方案

这就是我要解决的问题.

This is what I've come up with to solve the issue.

首先,我将CountryRegion表拆分为两个单独的类

First, I split the CountryRegion table into two separate classes

public partial class CountryRegionHeader
{
    public CountryRegionHeader()
    {
       StateProvinces = new HashSet<StateProvinceTlb>();
    }

    public string CountryRegionCode { get; set; }

    public string Name { get; set; }
}

public partial class CountryRegionDetail
{
    public CountryRegionDetail()
    {
        StateProvinces = new HashSet<StateProvinceTlb>();
    }

    public string CountryRegionCode { get; set; }


    public DateTime ModifiedDate { get; set; }

    public virtual ICollection<StateProvince> StateProvinces { get; set;}

    public virtual CountryRegion CountryRegion {get;set;}

}

然后我将新类的属性添加到StateProvince类中

I then add the properties for the new classes to my StateProvince class

[ForeignKey("CountryRegionCode)]
public CountryRegionHeader CountryRegionHeader {get;set;}

[ForeignKey("CountryRegionCode)]
public CountryRegionDetail CountryRegionDetail {get;set;}

然后我将DBSet添加到我的CountryRegionHeader和CountryRegionDetail的模型上下文中,并使用OnModelCreating方法中的流利API将它们绑定在一起

I then add the DBSets to my model context for CountryRegionHeader and CountryRegionDetail and tie them together using the fluent API in the OnModelCreating method

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<CountryRegionHeader>()
        .HasRequired(e => e.CountryRegionDetail)
        .WithRequiredPrincipal();
}

除此之外,我还创建了另一个名为CountryRegion的类,该类具有Header和Detail以及Header和Detail对象本身的所有属性.这些属性实际上指向标题和详细信息.这确实不是必需的,但是它使代码更整洁,更易于使用.另外,将数据向下发送到Web客户端时,我可以仅序列化CountryRegion对象,而排除Header和Detail对象.所以基本上我的CountryRegion类是这样的:

In addition to this, I've created another class just called CountryRegion which has all of the properties from both the Header and Detail as well as the Header and Detail object themselves. The properties actually point back to the header and detail. This really isn't necessary, but it makes the code cleaner and easier to use. Also, when sending the data down to a web client I can just serialize the CountryRegion object and exclude the Header and Detail object. So basically my CountryRegion class looks like this:

public Class CountryRegion
{
    public CountryRegionHeader Header;
    public CountryRegionDetail Detail;

    public CountryRegionCode
    {
       //need some special logic here for the key since both Header or
       //Detail share the primary key and both may not be loaded
       get
       {
           if (Header != null)
               return Header.CountryRegionCode;
           else
               return Detail.CountryRegionCode; 
        }
        set
        {
            if (Header != null) Header.CountryRegionCode = value;
            if (Detail != null) Detail.CountryRegionCode = value;
        }
    }

    public string Name
    {
        get
        {
            return Header.Name;
        }
        set
        {
            Header.Name = value;
        }

    }

    public DateTime ModifiedDate
    {
        get
        {
            return Detail.ModifiedDate ;
        }
        set
        {
            Detail.ModifiedDate = value;
        }

    }

    public virtual ICollection<StateProvince> StateProvinces
    {
        get
        {
            return Detail.StateProvinces ;
        }
        set
        {
            Detail.StateProvinces = value;
        }

    }

}

现在,当我查询时,我可以执行以下操作:

So, Now When I query I can do something like:

List<StateProvince> query =       db.StateProvince.Include(o=>o.CountryRegionHeader).ToList();

我只检索所需的数据,而没有检索整个CountryRegion记录

And I only retrieve the data I need without retrieving the entire CountryRegion record

此外,如果我仅使用CountryRegion,则可以这样查询:

Also, If I'm working with just the CountryRegion, I can query like this:

List<CountryRegion> query = (from a in db.CountryRegionHeader join b in    db.CountryRegionDetail on a.CountryRegionCode equals b.CountryRegionCode select new Employee(){Header = a, Detail = b}).ToList(); 

推荐答案

解决方案

这就是我要解决的问题.

This is what I've come up with to solve the issue.

首先,我将CountryRegion表拆分为两个单独的类

First, I split the CountryRegion table into two separate classes

public partial class CountryRegionHeader
{
    public CountryRegionHeader()
    {
       StateProvinces = new HashSet<StateProvinceTlb>();
    }

    public string CountryRegionCode { get; set; }

    public string Name { get; set; }
}

public partial class CountryRegionDetail
{
    public CountryRegionDetail()
    {
        StateProvinces = new HashSet<StateProvinceTlb>();
    }

    public string CountryRegionCode { get; set; }


    public DateTime ModifiedDate { get; set; }

    public virtual ICollection<StateProvince> StateProvinces { get; set;}

    pubic virtual CountryRegion CountryRegion {get;set;}

}

然后我将新类的属性添加到StateProvince类中

I then add the properties for the new classes to my StateProvince class

[ForeignKey("CountryRegionCode)]
public CountryRegionHeader CountryRegionHeader {get;set;}

[ForeignKey("CountryRegionCode)]
public CountryRegionDetail CountryRegionDetail {get;set;}

然后我将DBSet添加到我的CountryRegionHeader和CountryRegionDetail的模型上下文中,并使用OnModelCreating方法中的流利API将它们绑定在一起

I then add the DBSets to my model context for CountryRegionHeader and CountryRegionDetail and tie them together using the fluent API in the OnModelCreating method

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<CountryRegionHeader>()
        .HasRequired(e => e.CountryRegionDetail)
        .WithRequiredPrincipal();
}

除此之外,我还创建了另一个名为CountryRegion的类,该类具有Header和Detail以及Header和Detail对象本身的所有属性.该属性实际上指向标题和详细信息.这确实不是必需的,但是它使代码更整洁,更易于使用.另外,将数据向下发送到Web客户端时,我可以仅序列化CountryRegion对象,而排除Header和Detail对象.所以基本上我的CountryRegion类是这样的:

In addition to this, I've created another class just called CountryRegion which has all of the properties from both the Header and Detail as well as the Header and Detail object themselves. The properties actually point back to the header and detail. This really isn't necessary, but it makes the code cleaner and easier to use. Also, when sending the data down to a web client I can just serialize the CountryRegion object and exclude the Header and Detail object. So basically my CountryRegion class looks like this:

public Class CountryRegion
{
    public CountryRegionHeader Header;
    public CountryRegionDetail Detail;

    public CountryRegionCode
    {
       //need some special logic here for the key since both Header or
       //Detail share the primary key and both may not be loaded
       get
       {
           if (Header != null)
               return Header.CountryRegionCode;
           else
               return Detail.CountryRegionCode; 
       }
       set
       {
           if (Header != null) Header.CountryRegionCode = value;
           if (Detail != null) Detail.CountryRegionCode = value;
       }
   }

   public string Name
   {
       get
       {
           return Header.Name;
       }
       set
       {
           Header.Name = value;
       }

   }

   public DateTime ModifiedDate
   {
       get
       {
            return Detail.ModifiedDate ;
       }
       set
       {
            Detail.ModifiedDate = value;
       }

   }

   public virtual ICollection<StateProvince> StateProvinces
   {
      get
      {
           return Detail.StateProvinces ;
      }
      set
      {
           Detail.StateProvinces = value;
      }

   }

}

现在,当我查询时,我可以执行以下操作:

So, Now When I query I can do something like:

List<StateProvince> query =       db.StateProvince.Include(o=>o.CountryRegionHeader).ToList();

我只检索所需的数据,而没有检索整个CountryRegion记录

And I only retrieve the data I need without retrieving the entire CountryRegion record

此外,如果我仅使用CountryRegion,则可以这样查询:

Also, If I'm working with just the CountryRegion, I can query like this:

List<CountryRegion> query = (from a in db.CountryRegionHeader join b in    db.CountryRegionDetail on a.CountryRegionCode equals b.CountryRegionCode select new Employee(){Header = a, Detail = b}).ToList(); 

这篇关于实体框架参考属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆