1

GraphDiffを使用して切り離されたオブジェクト グラフを更新します。親とその子を保存するときに上記の例外が発生します。

モデルとマッピングは次のとおりです。

public class Group
{
    public int Id { get; set; }
    public virtual ICollection<GroupUser> Users{ get; set; }
}

public class GroupUser
{
    public int Id { get; set; }
    public int GroupId { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class GroupMap : EntityTypeConfiguration<Group>
{
    public GroupMap()
    {
        this.ToTable("groups");
        this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        this.HasMany(t => t.Users)
            .WithOptional()
            .HasForeignKey(d => d.GroupId)
            .WillCascadeOnDelete();
    }
}

public class GroupUserMap : EntityTypeConfiguration<GroupUser>
{
    public GroupUserMap ()
    {
        this.ToTable("groups_users");
        this.HasKey(t => t.Id).Property(t => t.Id).HasColumnName("id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(t => t.GroupId).HasColumnName("group_id").IsRequired();
        this.Property(t => t.UserId).HasColumnName("user_id").IsRequired();

        this.HasRequired(t => t.User)
            .WithMany()
            .HasForeignKey(d => d.UserId)
            .WillCascadeOnDelete(false);
    }
}

挿入と更新の場合、リポジトリに次のメソッドがあります。

public override Group Update(Group entity)
{
    if (entity.Users != null)
    {
        entity.Users.ToList()
                    .ForEach(x =>
                    {
                        x.GroupId = x.Id == 0 ? 0 : entity.Id;
                        x.UserId = x.User.Id;
                    });
    }

    return dbContext.UpdateGraph<Group>
        (entity,
            map => map.OwnedCollection(x => x.Users, with => with.AssociatedEntity(c => c.Users))
        );
}

私は次のことを行います:

  1. 新しいグループを追加し、保存してリロードします
  2. ユーザーをグループに追加し、保存してリロードします
  3. 2 番目のユーザーを追加し、保存してリロードします
  4. 3 番目のユーザーを追加し、保存を試みます -> 例外がスローされます

デバッグ中、追加されるユーザー エンティティの状態は常にデタッチされ、新しいエンティティに対して と の両方が 0 に設定されますGroupIdId追加された最初の 2 人のユーザーは正常に保存されます。ただし、3 番目のものでは、例外がスローされます。

いつも同じ方法で保存しているのに、うまくいかないのはなぜですか? それは問題ですEFGraphDiff、この問題を解決する方法はありますか?

ここSOおよび他の場所でのほとんどの質問と関連する回答はすべて、子エンティティが削除されている状況を扱っています。これは、私の特定のシナリオには当てはまりません。

4

3 に答える 3

1

EF によって追跡されていないときに、エンティティの状態が変更されているかどうかを確認してみましたか?

試す

db.Entry(currentUser).State = EntityState.Modified;

ToList() 関数が原因で、誤ってユーザー状態を変更してしまう可能性もあります。

于 2016-04-24T09:22:41.697 に答える
0

これを試してみてください。ただし、テストされていません

public override Group Update(Group entity)
{
    if (entity.Users != null)
    {
        foreach(var user in entity.Users){
          user.GroupId = x.Id == 0 ? 0 : entity.Id;
          user.UserId = x.User.Id;
         dbContext.Entry(child).State = EntityState.Modified;
        }

    }

    return dbContext.UpdateGraph<Group>
        (entity,
            map => map.OwnedCollection(x => x.Users, with => with.AssociatedEntity(c => c.Users))
        );
}
于 2016-04-28T22:35:08.633 に答える
0

おそらく、null 不可の UserId に関連しています。ご存じのとおり、UserId は EF で User を書き込むために使用されます。User が null の場合 (可能)、EF はエンティティを書き込むことができません。また、EF が Group.Users コレクションをマップするために使用する User.GroupId に関連している可能性もあります。

また、私はあなたのモデルを理解できません。ユーザーには 1 つのグループしかありません。グループには複数のユーザーを含めることができます。

これが本当なら、関連付けエンティティを削除してモデルを単純化してみませんか? EFはそれを必要としません...

public class Group
{
    public int Id { get; set; }
    public virtual ICollection<User> Users{ get; set; }
}

public class User
{
    public int Id { get; set; }
    public virtual Group Group { get; set; }
}

この場合、UserMap だけが必要です。

public class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        // You don't need to set primary key. EF take Id and create an identity column
        //HasKey(t => t.Id); 

        // Table & Column Mappings
        ToTable("users");
        // No column mappings in this case.

        // Relationships
        HasRequired(t => t.Group)
            .WithMany(t => t.Users)
            .Map(d => d.MapKey("user_group"));

    }
}

ユーザーが複数のグループを持つことができる場合、この方法でユーザーモデルを変更できます

public class User
{
    public int Id { get; set; }
    public virtual ICollection<Group> Groups { get; set; }
}

EF は、これが多対多の関係であることを理解しており、関連付けテーブル (UsersGroups) を作成しますが、関連付けエンティティは必要ありません。

編集

db.Entry(myEntity).State = EntityState.Modified;EF6で設定する必要があることはほとんどありません。プロキシは非常にうまく機能します。

于 2016-04-29T06:15:26.087 に答える