【问题标题】:Splitting an Entity with navigational property into two tables using EF4.1 Fluent API使用 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();

        }
      }

【问题讨论】:

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


    【解决方案1】:

    导航属性不直接映射到表,因此您必须从映射到Users 表中删除AuthProvider

          Map(mc => {
            mc.Properties(x => new {
              x.Id,
              x.Username,
              x.Email
            });
            mc.ToTable("Users");
          });
    

    我很确定我已经在某个地方回答了这个问题。

    编辑:

    这回答了你的问题。您想要实体拆分,这是实体拆分的正确映射。实体拆分不允许没有个人资料的用户。一旦你使用它,每个用户都必须有一个配置文件——这是实体拆分的先决条件。您的选择是:

    • 您必须拥有每个用户的配置文件,然后才能使用实体拆分并将两个表映射到单个实体。如果您没有每个用户的个人资料,请修改您的数据库并确保每个用户都有空个人资料。
    • 如果您没有每个用户的配置文件并且您不想创建空配置文件,则不能使用实体拆分 = 您不能将这些表映射到单个实体,您必须使用具有一对一关系的两个实体而是。

    一旦您使用实体拆分,它的行为就与任何其他实体完全一样——它总是加载所有属性,这就是内部连接的原因。你不能只加载一半的属性(除了投影,但它仍然在内部执行主查询)。

    【讨论】:

    • 非常感谢,但这并不能回答我的问题。如果我删除它并调用 dbcontext.Users,它会与 UserProfiles 表进行内部连接。也就是说,如果我告诉它获取所有用户,EF 最终会与 UserProfiles 表进行内部联接,因此如果用户配置文件表中没有数据,我总是得到零行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多