使用 EF4.1 Fluent API 将具有导航属性的实体拆分为两个表
Posted
技术标签:
【中文标题】使用 EF4.1 Fluent API 将具有导航属性的实体拆分为两个表【英文标题】:Splitting an Entity with navigational property into two tables using EF4.1 Fluent API 【发布时间】:2011-07-06 20:23:32 【问题描述】:我有一个用户表和一个用户配置文件表。一个用户有零个或只有一个用户配置文件。 (即一对一的关系)有人可以帮助我使用 EF4.1 fluent API 将用户实体映射到用户和用户配置文件表。下面是表格的详细信息。用户和 AuthProvider 也有一对多的关系。
// 1. Users Table has the columns(UserId(PK), UserName, Email, AuthProviderId(FK))
// 2. UserProfiles Table has columns(UserId(PK/FK), FirstName, MiddleName,LastName)
// 3. AuthProvider Table has columns (AuthProviderId(PK), AuthName)
public class User
public User()
Id = Guid.NewGuid();
public virtual Guid Id get; private set;
public virtual string Username get; set;
public virtual string Email get; set;
public virtual AuthProvider AuthProvider get; set;
public virtual string FirstName get; set;
public virtual string MiddleName get; set;
public virtual string LastName get; set;
public class AuthProvider
public AuthProvider()
Id = Guid.NewGuid();
public virtual Guid Id get; private set;
public virtual string Name get; set;
public virtual ICollection<User> Users get; set;
// This is the Mappings
public class UserConfiguration : EntityTypeConfiguration<User>
public UserConfiguration()
HasKey(x => x.Id).Property(x => x.Id).HasColumnName("UserId").IsRequired();
Property(x => x.Username).HasColumnName("Username").IsRequired();
Property(x => x.Email).HasColumnName("Email").IsRequired();
Property(x => x.FirstName).HasColumnName("FirstName").IsOptional();
Property(x => x.MiddleName).HasColumnName("MiddleName").IsOptional();
Property(x => x.LastName).HasColumnName("LastName").IsOptional();
HasRequired(x => x.AuthProvider).WithMany(x => x.Users).Map(x => x.MapKey("AuthProviderId"));
Map(mc =>
mc.Properties(x => new
x.Id,
x.Username,
x.Email,
x.AuthProvider
);
mc.ToTable("Users");
);
Map(mc =>
mc.Properties(x => new x.Id, x.FirstName, x.MiddleName, x.LastName );
mc.ToTable("UserProfiles");
);
public class AuthProviderConfiuration : EntityTypeConfiguration<AuthProvider>
public AuthProviderConfiuration()
ToTable("AuthProviders");
HasKey(x => x.Id).Property(x => x.Id).HasColumnName("AuthProviderId").IsRequired();
Property(x => x.Name).HasColumnName("ProviderName").IsRequired();
【问题讨论】:
【参考方案1】:导航属性不直接映射到表,因此您必须从映射到Users
表中删除AuthProvider
:
Map(mc =>
mc.Properties(x => new
x.Id,
x.Username,
x.Email
);
mc.ToTable("Users");
);
我很确定我已经在某个地方回答了这个问题。
编辑:
这回答了你的问题。您想要实体拆分,这是实体拆分的正确映射。实体拆分不允许没有个人资料的用户。一旦你使用它,每个用户都必须有一个配置文件——这是实体拆分的先决条件。您的选择是:
您必须拥有每个用户的配置文件,然后才能使用实体拆分并将两个表映射到单个实体。如果您没有每个用户的个人资料,请修改您的数据库并确保每个用户都有空个人资料。 如果您没有每个用户的配置文件并且您不想创建空配置文件,则不能使用实体拆分 = 您不能将这些表映射到单个实体,您必须使用具有一对一关系的两个实体而是。一旦您使用实体拆分,它的行为就与任何其他实体完全一样——它总是加载所有属性,这就是内部连接的原因。你不能只加载一半的属性(除了投影,但它仍然在内部执行主查询)。
【讨论】:
非常感谢,但这并不能回答我的问题。如果我删除它并调用 dbcontext.Users,它会与 UserProfiles 表进行内部连接。也就是说,如果我告诉它获取所有用户,EF 最终会与 UserProfiles 表进行内部联接,因此如果用户配置文件表中没有数据,我总是得到零行。以上是关于使用 EF4.1 Fluent API 将具有导航属性的实体拆分为两个表的主要内容,如果未能解决你的问题,请参考以下文章
EF 4.1:使用 Fluent 映射从 Code First 中查找关键属性类型
实体框架(CTP5、Fluent API)。重命名导航属性的列
Fluent API:如何将 HasComputedColumnSql 与外键对象一起使用