EF Code First:像复杂类型一样处理实体(非规范化)

时间:2011-05-31 19:55:48

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

我正在使用EF 4.1 Code First,我正在制作一个可配置的实用程序来解析/导入大分隔文件。文件中的每一行都可能包含多个实体的数据。

文件的确切数据和布局在构建时是未知的(每个客户端的配置都不同),所以我可以配置它。

示例模型(简化)

public class Contact {
    public int Id { get; set;}
    public string Name { get; set; }
}

public class Account {
    public int Id { get; set; }
    public decimal Balance { get; set; }
    public bool IsOpen { get; set; }
}

根据客户端的不同,文件可能包含联系信息,帐户信息或两者。由于这些文件的大小(大量记录),我们必须使用SqlBulkCopy来进行数据加载。在编译时也不知道将对数据运行哪些规则(客户端的验证更改等)

我希望有一个表和类,比如ImportRecord,来保存导入的数据。我现在的工人阶级就像:

public class ImportRecord {
    public string Contact_Name { get; set; }
    public decimal Account_Balance { get; set; }
    public bool Account_IsOpen { get; set; }
}

这里的问题是,当我们在模型类中添加/更改字段时,ImportRecord也必须更改 - 它是重复/不太理想。对我来说,导入数据驻留在单个表中以简化SqlBulkCopy导入对我来说有点重要。

我理想的ImportRecord类看起来像这样:

public class ImportRecord {
    public Contact Contact { get; set; }
    public Account Account { get; set; }
}

但是这只会创建一个包含两个外键的表(除了抱怨没有FK属性)。有没有办法让实体类的行为更像是ImportRecord的非规范化,无密钥,复杂类型?我完全错了吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

实体不能嵌套,同时复杂类型不能有实体键,所以你不能使用一个而不是其他,但你可以尝试这个小作弊。我刚测试它至少创建了正确的数据库结构:

public class Context : DbContext
{
    public DbSet<Account> Accounts { get; set; }
    public DbSet<Contact> Contacts { get; set; }
    public DbSet<ImportRecord> ImportRecords { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.ComplexType<ContactBase>();
        modelBuilder.ComplexType<AccountBase>();
    }
}

public class ContactBase
{
    public string Name { get; set; }
}

public class AccountBase
{
    public decimal Balance { get; set; }
    public bool IsOpen { get; set; }
}

public class Contact : ContactBase
{
    public int Id { get; set; }
}

public class Account : AccountBase
{
    public int Id { get; set; }
}

public class ImportRecord
{
    public int Id { get; set; }
    public ContactBase Contact { get; set; }
    public AccountBase Account { get; set; }
}