首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有重复列的映射表到同一类的两个实例

具有重复列的映射表到同一类的两个实例
EN

Stack Overflow用户
提问于 2015-12-31 18:19:47
回答 2查看 198关注 0票数 2

我有一个如下所示的数据库。是的,我知道,我继承了一个糟糕的设计,但现在不能改变。基本上,每个客户都可以获得主要和次要的联系信息:

客户

  • id
  • customer_number
  • 其他东西

ContactInfo

  • customer_id
  • primary_name
  • primary_email
  • primary_phone
  • secondary_name
  • secondary_email
  • secondary_phone
  • updated_at

我希望我的实体框架6域模型看起来如下:

代码语言:javascript
复制
public class Customer
{
    public int Id { get; set; }
    public string CustomerNumber { get; set; }

    public ContactInfo PrimaryContactInfo { get; set; }
    public ContactInfo SecondaryContactInfo { get; set; }
}

public class ContactInfo
{
    public int CustomerId { get; set; }

    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public DateTime? UpdatedAt { get; set; }

    public virtual Customer Customer { get; set; }
}

是否有一种方法来设置映射,以便这是可能的?本质上,将列"primary__“映射到ContactInfo的一个实例,将列"secondary__”映射到另一个实例,并将一些列映射到两个实例?

或者,可以将字段映射到两个复杂类型的实例:

代码语言:javascript
复制
public class ContactInfo
{
    public int CustomerId { get; set; }

    public SingleContactInfo Primary { get; set; }
    public SingleContactInfo Secondary { get; set; }

    public virtual Customer Customer { get; set; }
}

public class SingleContactInfo
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
}
EN

Stack Overflow用户

回答已采纳

发布于 2016-01-02 00:20:09

第一个解决方案(继承)无法完成,因为不可能将继承方案中的两个实体保存到一个数据库记录中。

第二种解决方案(复杂类型)确实有效,但您必须牺牲将ContactInfo作为独立实体来处理并在模型中包含updated_at的能力。(因为updated_at不能两次映射到一个复杂类型的属性)。

我看到的唯一方法是将实体映射到数据模型,同时保持ContactInfo作为一个独立的实体集(几乎)和读写updated_at的能力,即通过表拆分。

在这个映射中,表ContactInfo被分成两个实体-- ContactInfoPrimaryContactInfoSecondaryCustomerContactInfoPrimary有1:1的关联,其中包含ContactInfoSecondary

看上去是这样的:

课程:

代码语言:javascript
复制
public partial class Customer
{
    public int Id { get; set; }
    public string CustomerNumber { get; set; }
    public virtual ContactInfoPrimary ContactInfoPrimary { get; set; }
}

public abstract class ContactInfo
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
}

public class ContactInfoPrimary : ContactInfo
{
    public DateTime UpdatedAt { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual ContactInfoSecondary ContactInfoSecondary { get; set; }
}

public class ContactInfoSecondary : ContactInfo
{ }

映射:

代码语言:javascript
复制
class CustomerMap : EntityTypeConfiguration<Customer>
{
    public CustomerMap()
    {
        ToTable("Customer");
        HasKey(c => c.Id);
        Property(c => c.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
            .HasColumnName("id");
        Property(c => c.CustomerNumber)
            .HasColumnName("customer_number");
        HasOptional(c => c.ContactInfoPrimary).WithRequired(ci => ci.Customer);
    }    
}

class ContactInfoPrimaryMap : EntityTypeConfiguration<ContactInfoPrimary>
{
    public ContactInfoPrimaryMap()
    {
        ToTable("ContactInfo");
        HasKey(ci => ci.CustomerId);
        Property(ci => ci.CustomerId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
            .HasColumnName("customer_id");
        Property(ci => ci.UpdatedAt).HasColumnName("updated_at");
        Property(ci => ci.Name).HasColumnName("primary_name");
        Property(ci => ci.Email).HasColumnName("primary_email");
        Property(ci => ci.Phone).HasColumnName("primary_phone");

        // This, and the ToTable statements, define the table splitting.
        HasRequired(ci => ci.ContactInfoSecondary).WithRequiredPrincipal();
    }
}

class ContactInfoSecondaryMap : EntityTypeConfiguration<ContactInfoSecondary>
{
    public ContactInfoSecondaryMap()
    {
        ToTable("ContactInfo");
        HasKey(ci => ci.CustomerId);
        Property(ci => ci.CustomerId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
            .HasColumnName("customer_id");
        Property(ci => ci.Name).HasColumnName("secondary_name");
        Property(ci => ci.Email).HasColumnName("secondary_email");
        Property(ci => ci.Phone).HasColumnName("secondary_phone");
    }
}

以及背景:

代码语言:javascript
复制
public partial class TestSO : DbContext
{
    public TestSO() : base("name=TestSO")
    { }

    public virtual DbSet<ContactInfoPrimary> ContactInfoes { get; set; }
    public virtual DbSet<Customer> Customers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new CustomerMap());
        modelBuilder.Configurations.Add(new ContactInfoPrimaryMap());
        modelBuilder.Configurations.Add(new ContactInfoSecondaryMap());
    }
}

现在您可以创建一个包含联系人信息的Customer,如下所示:

代码语言:javascript
复制
var cis = new ContactInfoSecondary
            {
                Name = "Name2",
                Email = "email2",
                Phone = "phone2"
            };
var cip = new ContactInfoPrimary
            {
                Name = "Name1",
                Email = "email1",
                Phone = "phone1",
                UpdatedAt = DateTime.Today,
                ContactInfoSecondary = cis
            };
var cst = new Customer
            {
                ContactInfoPrimary = cip,
                CustomerNumber = "number-nine"
            };
context.Customers.Add(cst);
context.SaveChanges();

以下是如何获取所有信息的客户:

代码语言:javascript
复制
context.Customers.Include(c => c.ContactInfoPrimary.ContactInfoSecondary)

或单独提供联系信息:

代码语言:javascript
复制
context.ContactInfoes.Include(c => c.ContactInfoSecondary)

你明白我为什么说你几乎可以独立获得ContactInfo了。不完全是。你只能在初选中获得第二名。

票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34550229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档