实体框架如何映射复合实体?

时间:2018-07-16 16:13:45

标签: entity-framework ef-code-first-mapping

我是EF的新手,我有这样的问题: 我有四个实体,它们描述地址的元素:

public partial class Region : BaseEntity
{
    private ICollection<RegionCity> _regionCities;

    public string Code { get; set; }
    public string Name { get; set; }
    public int Timezone { get; set; }

    public virtual ICollection<RegionCity> RegionCities
    {
        get
        {
            return _regionCities ?? (_regionCities = new List<RegionCity>());
        }
        protected set { _regionCities = value; }
    }
}

public partial class RegionCity : BaseEntity
{
    private ICollection<CityStreet> _cityStreets;

    public int RegionId { get; set; }
    public string CityName { get; set; }

    public virtual Region Region { get; set; }

    public virtual ICollection<CityStreet> CityStreets
    {
        get { return _cityStreets ?? (_cityStreets = new List<CityStreet>()); }
        protected set { _cityStreets = value; }
    }
}

public partial class CityStreet : BaseEntity
{
    public int CityId { get; set; }
    public string StreetName { get; set; }

    public virtual RegionCity City { get; set; }
}

public partial class FullAddress : BaseEntity
{
    public int CityStreetId { get; set; }
    public string HouseNum { get; set; }
    public string OfficeNum { get; set; }

    public virtual CityStreet Street { get; set; }
}

我有映射类:

public class RegionMap : EntityTypeConfiguration<Region>
{
    public RegionMap()
    {
        this.ToTable("Region");
        this.HasKey(r => r.Id);
        this.Property(r => r.Name).HasMaxLength(64);
    }
}

public class RegionCityMap : EntityTypeConfiguration<RegionCity>
{
    public RegionCityMap()
    {
        this.ToTable("RegionCity");
        this.HasKey(rc => rc.Id);

        this.HasRequired(rc => rc.Region)
            .WithMany(r => r.RegionCities)
            .HasForeignKey(rc => rc.RegionId)
            .WillCascadeOnDelete(false);
    }
}

public class CityStreetMap : EntityTypeConfiguration<CityStreet>
{
    public CityStreetMap()
    {
        this.ToTable("CityStreet");
        this.HasKey(cs => cs.Id);

        this.HasRequired(cs => cs.City)
            .WithMany(c => c.CityStreets)
            .HasForeignKey(cs => cs.CityId)
            .WillCascadeOnDelete(false);
    }
}

public class FullAddressMap : EntityTypeConfiguration<FullAddress>
{
    public FullAddressMap()
    {
        this.ToTable("FullAddress");
        this.HasKey(fu => fu.Id);
        this.Property(fu => fu.HouseNum).HasMaxLength(16);

        this.HasRequired(fu => fu.Street)
            .WithMany()
            .HasForeignKey(fu => fu.CityStreetId)
            .WillCascadeOnDelete(false);
    }
}

如果要按如下所示更改类FullAddress,我将如何编写映射类,以使其名称合理:

public partial class FullAddress : BaseEntity
{
    public int CityStreetId { get; set; }
    public string HouseNum { get; set; }

    public virtual Region Region { get; set; }
    public virtual RegionCity City { get; set; }
    public virtual CityStreet Street { get; set; }
}

我可以通过CityStreet然后通过RegionCity映射RegionCity吗?

1 个答案:

答案 0 :(得分:1)

您可以使用NotMapped属性遍历层次结构。或者,您可以声明跳过级别的其他Navigaion属性和外键。

如果将键结构更改为使用复合键(无论如何,IMO在这里都是最佳做法),则可以执行任一操作。

例如

public class BaseEntity
{

}

public partial class Region : BaseEntity
{
    public int RegionID { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
    public int Timezone { get; set; }

    public virtual ICollection<RegionCity> RegionCities { get; } = new HashSet<RegionCity>();
}


public partial class RegionCity : BaseEntity
{

    [Key(), Column(Order=0)]
    public int RegionId { get; set; }
    [Key(), Column(Order = 1)]
    public int RegionCityId { get; set; }
    public string CityName { get; set; }

    [ForeignKey("RegionId")]
    public virtual Region Region { get; set; }

    public virtual ICollection<CityStreet> CityStreets { get; } = new HashSet<CityStreet>();

}

public partial class CityStreet : BaseEntity
{

    [Key(), Column(Order = 0)]
    public int RegionId { get; set; }

    [Key(), Column(Order = 1)]
    public int RegionCityId { get; set; }

    [Key(), Column(Order = 3)]
    public int CityStreetId { get; set; }

    public string StreetName { get; set; }

    [ForeignKey("RegionId,RegionCityId")]
    public virtual RegionCity RegionCity { get; set; }

    public virtual ICollection<FullAddress> FullAddresses { get; } = new HashSet<FullAddress>();
}

public partial class FullAddress : BaseEntity
{

    [Key(), Column(Order = 0)]
    public int RegionId { get; set; }

    [Key(), Column(Order = 1)]
    public int RegionCityId { get; set; }

    [Key(), Column(Order = 3)]
    public int CityStreetId { get; set; }

    [Key(), Column(Order = 4)]
    public int FullAddressId { get; set; }
    public string HouseNum { get; set; }
    public string OfficeNum { get; set; }

    [ForeignKey("RegionId,RegionCityId,CityStreetId")]
    public virtual CityStreet Street { get; set; }

    [NotMapped]
    public virtual RegionCity RegionCity 
    {
        get
        {
            return this.Street.RegionCity;
        }
        set
        {
            this.Street.RegionCity = value;
        }
    }


    [NotMapped]
    public virtual Region Region
    {
        get
        {
            return this.Street.RegionCity.Region;
        }
        set
        {
            this.Street.RegionCity.Region = value;
        }
    }

}