【问题标题】:Entity Framework 5 - Insert data into UsersInRoles Many to Many tableEntity Framework 5 - 将数据插入到 UsersInRoles 多对多表中
【发布时间】:2013-04-25 14:18:17
【问题描述】:

我有一个场景,我需要在不使用 ASP.NET 成员资格的情况下手动将用户、角色和 UsersInRoles 条目插入数据库。现在,当我尝试插入多对多关系 UsersInRoles 时,我得到以下异常

Invalid column name 'Role_RoleId'.

我正在使用 EF 5,即 POCO 的数据库优先方法。我已经在 EDMX 中定义了一个关联,所以应该没问题...这里是模型实体

/// <summary>
/// No Metadata Documentation available.
/// </summary>
[DataContract(IsReference = true)]
[KnownType(typeof(User))]
public partial class User  : IUser 
{
    #region Primitive Properties
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual System.Guid ApplicationId
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual System.Guid UserId
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual string UserName
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual bool IsAnonymous
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual System.DateTime LastActivityDate
    {
        get;
        set;
    }

    #endregion

    #region Navigation Properties
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [NotMapped]
    public virtual IMembership Membership
    {
        get { return _membership; }
        set
        {
            if (!ReferenceEquals(_membership, value))
            {
                var previousValue = _membership;
                _membership = value;
                FixupMembership(previousValue);
            }
        }
    }
    private IMembership _membership;
    /// <summary>
    /// Gets or sets the roles associated with an user
    /// </summary>   
    [DataMember]    
    public virtual ICollection<Role> Roles
    {
        get
        {
            if (_roles == null)
            {
                _roles = new FixupCollection<Role>();
            }
            return _roles;
        }
        set
        {
            _roles = value;
        }
    }
    private ICollection<Role> _roles;

    #endregion

    #region Association Fixup

    private void FixupMembership(IMembership previousValue)
    {
        if (previousValue != null && ReferenceEquals(previousValue.User, this))
        {
            previousValue.User = null;
        }

        if (Membership != null)
        {
            Membership.User = this;
        }
    }

    #endregion

}

注意:这是从用户到角色的单向关系

/// <summary>
/// No Metadata Documentation available.
/// </summary>
[DataContract]
[KnownType(typeof(Role))]
public partial class Role  : IRole 
{
    #region Primitive Properties
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual System.Guid ApplicationId
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual System.Guid RoleId
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual string RoleName
    {
        get;
        set;
    }
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [DataMember]    
    public virtual string Description
    {
        get;
        set;
    }

    #endregion      

}

工作代码

MyContext context = new MyContext();

Role usersRole = new Role();
usersRole.RoleName = "Users";
usersRole.Description = "User Role";
usersRole.RoleId = GuidExtension.NewSequentialGuid();
usersRole.ApplicationId = application.Id;

//Init users
User adminUser = new User();
adminUser.UserName = "admin";
adminUser.IsAnonymous = false;
adminUser.LastActivityDate = DateTime.UtcNow;
adminUser.UserId = GuidExtension.NewSequentialGuid();
adminUser.ApplicationId = application.Id;
//Init user roles
adminUser.Roles.Add(usersRole);

context.User.Add(adminUser);
context.SaveChanges();

我也尝试过先将角色添加到数据库,然后添加一个用户(没有将角色添加到角色集合),我得到了同样的异常。然后我通过 Fluent API 添加了模型绑定,如下所示:

modelBuilder.Entity<User>()
              .HasMany(u => u.Roles)
              .WithMany()
              .Map(m =>
              {
                  m.MapLeftKey("UserId");
                  m.MapRightKey("RoleId");
                  m.ToTable("UsersInRoles");
              });

我也尝试像这样添加绑定:

modelBuilder.Entity<User>()
          .HasMany(u => u.Roles)
          .WithMany()
          .Map(m =>
          {
              m.MapLeftKey("UserId");
              m.MapRightKey("RoleId");
              var mapping = m.ToTable("UsersInRoles");
              mapping.MapLeftKey("UserId");
              mapping.MapRightKey("RoleId");
          });

还有上面代码的 SQL Trace

exec sp_executesql N'insert [dbo].[Roles]([RoleId], [ApplicationId], [RoleName], [Description])
values (@0, @1, @2, @3)
',N'@0 uniqueidentifier,@1 uniqueidentifier,@2 nvarchar(max) ,@3 nvarchar(max) ',@0='46E39982-E490-4F79-B457-A1AB012948CE',@1='79D75E2D-9923-48DC-A4D6-AE0CED0EDD58',@2=N'Users',@3=N'User Role'

exec sp_executesql N'insert [dbo].[Users]([UserId], [ApplicationId], [UserName], [IsAnonymous], [LastActivityDate], [Role_RoleId])
values (@0, @1, @2, @3, @4, null)
',N'@0 uniqueidentifier,@1 uniqueidentifier,@2 nvarchar(max) ,@3 bit,@4 datetime2(7)',@0='B5EA5052-71C9-411E-91C7-A1AB012948CF',@1='79D75E2D-9923-48DC-A4D6-AE0CED0EDD58',@2=N'admin',@3=0,@4='2013-04-25 14:14:08.4930381'

您可以在上面看到问题的根源,用户插入 SQL 中的 [Role_RoleId] 列,所以我不确定我是否正确设置了导航属性?

无论我做什么,都会忽略上述异常,例如 Fluent API 绑定。有谁知道如何正确地将多对多条目添加到 UsersInRoles 表中,或者我的代码中缺少什么。

注意:我是 EF 新手,所以任何信息都会有所帮助。

更新 我试图只将用户条目保存到数据库中,但我得到了相同的 [Role_RoleId] 异常,希望这能进一步澄清这个问题,因为这可能不是多对多插入问题而是无效的多对多配置问题?

问候

【问题讨论】:

    标签: entity-framework asp.net-membership entity-framework-5 fluent-interface


    【解决方案1】:

    我在我的代码中发现了两个问题,经过长时间的代码审查,第一个问题是我的一个名为的部分类中的“隐藏”属性

    public virtual ICollection<User> Members { get; set; }
    

    这是一个复制粘贴错误,我找不到它,因为它位于折叠区域中,我正在寻找 Users 属性,因为这是我之前生成的导航项的名称。

    第二个问题比较严重,漏掉了,和“Database.SetInitializer”有关,db initializer被放进去

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      Database.SetInitializer<CoreDALContext>(null);
    }
    

    这是错误的,这应该只被调用一次,并按照微软的实现放入静态构造函数中。

    static CoreDALContext()
    {
      Database.SetInitializer<CoreDALContext>(null);
    }
    

    我希望这将帮助其他 EF 新人不要犯同样的错误。

    问候

    【讨论】:

      猜你喜欢
      • 2020-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      相关资源
      最近更新 更多