【问题标题】:How to properly map entities using Fluent API?如何使用 Fluent API 正确映射实体?
【发布时间】:2012-07-11 17:49:43
【问题描述】:

我有两个实体,一个用户和一个用户配置文件。 User的PK是UserId,UserProfile的PK是UserProfileId。每次在我的应用程序中创建新用户时,我都会创建一个新的 UserProfile,其 PK 与 User 中的 PK 相同。然后,当我尝试更新 UserProfile 上的属性时,我最终会收到多重错误或架构无效错误。这是我的两个实体:

public class User
{
    public Guid UserId { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? PhoneExtension { get; set; }
    public string Comment { get; set; }
    public Boolean IsApproved { get; set; }
    public int PasswordFailuresSinceLastSuccess { get; set; }
    public DateTime? LastPasswordFailureDate { get; set; }
    public DateTime? LastActivityDate { get; set; }
    public DateTime? LastLockoutDate { get; set; }
    public DateTime? LastLoginDate { get; set; }
    public string ConfirmationToken { get; set; }
    public DateTime? CreateDate { get; set; }
    public Boolean IsLockedOut { get; set; }
    public DateTime? LastPasswordChangedDate { get; set; }
    public string PasswordVerificationToken { get; set; }
    public DateTime? PasswordVerificationTokenExpirationDate { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
    public virtual UserProfile UserProfile { get; set; }
}


public class UserProfile
{
    public Guid UserProfileId { get; set; } 
    public virtual User ProfileOwner { get; set; }
    public Int64? HomePhone { get; set; }
    public Int64? MobilePhone { get; set; }

    public virtual User Manager { get; set; }
}

..这是我使用 Fluent API 定义的唯一关系。

modelBuilder.Entity<UserProfile>()
        .HasKey(e => e.UserProfileId);
modelBuilder.Entity<UserProfile>()
        .Property(e => e.UserProfileId)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<UserProfile>()
        .HasRequired(e => e.ProfileOwner)
        .WithRequiredDependent(r => r.UserProfile);

最后,我的 UserService 创建了一个新用户,同时创建了一个新的 UserProfile,其 Guid UserProfileId 与用户的 Guid UserId 相同。在创建用户和配置文件后,我尝试使用我的 UserProfileService 更新 UserProfile 中的管理器:

public void UpdateUserProfile(UserProfile updatedUserProfile)
{
    UserProfile oldUserProfile = GetUserProfileByID(updatedUserProfile.UserProfileId);

    oldUserProfile.Manager = updatedUserProfile.Manager;
    oldUserProfile.HomePhone = updatedUserProfile.HomePhone;
    oldUserProfile.MobilePhone = updatedUserProfile.MobilePhone;

    this.SetEntityState(oldUserProfile, EntityState.Modified);
    this.UnitOfWork.SaveChanges();
}

this.SetEntityState 行抛出此错误:

违反了多重性约束。关系“WhelenPortal.Data.Context.UserProfile_ProfileOwner”的角色“UserProfile_ProfileOwner_Source”的多重性为 1 或 0..1。

我已经尝试了两天了,请帮忙!!!提前致谢。

根据要求,这里有一些附加信息。我在这里使用存储库模式和工作单元。我的 GetUserProfileById 代码如下。该服务使用存储库,因此我将两者都显示。

public UserProfile GetUserProfileByID(Guid id)
{
    if (id == null)
        throw new BusinessServicesException(Resources.UnableToRetrieveUserProfileExceptionMessage, new ArgumentNullException("id"));

    try
    {
        Model.UserProfile userProfile = _userProfileRepository.GetUserProfileByID(id);

        if (userProfile != null)
            return ToServicesUserProfile(userProfile);

        return null;
    }
    catch (InvalidOperationException ex)
    {
        throw new BusinessServicesException(Resources.UnableToRetrieveUserProfileExceptionMessage, ex);
    }
}

..和存储库:

public UserProfile GetUserProfileByID(Guid id)
{
    return this.GetDbSet<UserProfile>().Find(id);
}

【问题讨论】:

  • 你能显示GetUserProfileByID和SetEntityState吗?所有涉及的方法都使用相同的上下文实例吗?如果他们这样做,你为什么将状态设置为Modified?更改跟踪会将更改的属性标记为自动修改。
  • 我已更新问题以包含您要求的信息。
  • 嗯? ToServicesUserProfile(userProfile),那里发生了什么?
  • 这是一个 n 层项目,所以我有一个业务层、数据层和 Web 层。 ToServicesUserProfile(userProfile) 本质上将模型对象映射到业务层的模型对象。整个项目非常紧密地遵循 Project Silk 的结构。您可以在此处的 MSDN 上看到:msdn.microsoft.com/en-us/library/hh396380.aspx 或在此处的 codeplex 上:silk.codeplex.com
  • 乍一看,您的映射在我看来是正确的。魔鬼可能在某些细节上。问题是 EF 详细信息(对于回答您的问题很重要)非常隐藏在您的体系结构和许多方法调用下。您能否尝试从所有这些方法中提取相关代码,以便清楚地查看上下文何时使用、哪些查询以及其他 DbContext 和 DbSet 方法?

标签: entity-framework foreign-keys code-first fluent


【解决方案1】:

所以在玩了很多之后,这最终对我有用,希望它可以以某种方式帮助其他人。我的 User 类保持不变,但我的 UserProfile 类更改为:

public class UserProfile
{
    public Guid UserProfileId { get; set; }
    public virtual User ProfileOwner { get; set; }

    public Guid? ManagerId { get; set; }
    public virtual User Manager { get; set; }

    public Int64? HomePhone { get; set; }
    public Int64? MobilePhone { get; set; }
}

这是流畅的映射:

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

    modelBuilder.Entity<User>()
        .HasOptional(u => u.UserProfile)
        .WithRequired(u => u.ProfileOwner);

    modelBuilder.Entity<UserProfile>()
        .HasOptional(u => u.Manager)
        .WithMany()
        .HasForeignKey(u => u.ManagerId);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 2011-05-29
    • 2020-03-21
    • 2014-12-31
    • 1970-01-01
    • 2014-08-24
    相关资源
    最近更新 更多