1

ASP.NET メンバーシップを使用せずに、User、Roles、UsersInRoles エントリをデータベースに手動で挿入する必要があるシナリオがあります。多対多のリレーション UsersInRoles を挿入しようとすると、次の例外が発生します

Invalid column name 'Role_RoleId'.

POCOを使用したEF 5、データベースファーストアプローチを使用しています。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 トレースもここにあります

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 を初めて使用するので、どんな情報でも役に立ちます。

更新 User エントリのみをデータベースに保存しようとしましたが、同じ[Role_RoleId]例外が発生しました。おそらくこれは多対多の挿入の問題ではなく、無効な多対多であるため、この問題がもう少し明確になることを願っています設定の問題?

よろしく

4

1 に答える 1

0

コードに 2 つの問題が見つかりました。長いコード レビューの後、最初の問題は、呼び出された部分クラスの 1 つでプロパティが「隠されている」ことでした。

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

コピー アンド ペースト エラーとして表示されていましたが、折りたたまれた領域にあったため見つかりませんでした。以前に生成したナビゲーション アイテムの名前だったので、Users プロパティを探していました。

2番目の問題は、すり抜けたより深刻な問題であり、「Database.SetInitializer」に関連し、dbイニシャライザが挿入されました

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

これは間違っており、これは一度だけ呼び出して、Microsoft の実装に従って静的コンストラクターに入れる必要があります。

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

これが、他の EF 初心者が私と同じ過ちを犯さないようにするのに役立つことを願っています。

よろしく

于 2013-04-30T11:55:28.620 に答える