0

内部にある親オブジェクトと子オブジェクトを変更するレコードタイプのグラフを更新したいと思います。この問題は通常、子のEF UPDATEレジストリが子をNULLに設定し、子が更新しているレコードを識別するのに役立つ場合に発生します。

私のドメインクラスは次のとおりです。

このクラスは、ステータスを変更するのに役立ちます。追加-カスタマイズ-削除。これは、すべての子としての親からのグラフです。それを機能させる機能。

public interface IObjectWthState
{
    State State { get; set; }
}
public enum State 
{
    Added,
    Unchanged,
    Modified,
    Deleted
}

これはユーザークラスです:

 public abstract class User : IObjectWthState 
 {
    public int Id { get; set; }
    public String Name { get; set; }
    public String LastName { get; set; }        
    [Timestamp]
    public byte[] RowVersion { get; set; }
    [NotMapped]
    public State State { get; set; }
}

そして、これがユーザーから継承する2つのクラスです。

public class AdminUser:User
{
    public ICollection<BasicUser> UsersList { get; set; }
    public String Email { get; set; }
}

public class BasicUser: User
{
    public String Position { get; set; }
    public String Department { get; set; }
}

ご覧のとおり、AdminUserBasicUserにはリストがあります。

モデルは必要に応じて生成され、外部キーを検出して追加する必要がありました。ここにDBの写真があります:

移行で生成されたモデル

これは、情報を追加または更新する関数です。

public virtual void AddUpdateGraph(T entity)
{

    if (((IObjectWthState)entity).State == State.Added)
    {
        DbEntityEntry dbEntityEntry = dbContext.Entry(entity);
        dbEntityEntry.State = EntityState.Added;
    }
    else
    {
        dbSet.Add(entity);
        dbContext.ApplyStateChanges();
    }
} 

goを処理し、内部ノードのステータスを調整する関数は次のとおりです。

public static void ApplyStateChanges(this DbContext context)
{
    foreach (var entry in context.ChangeTracker.Entries<IObjectWthState>())
    {
        IObjectWthState stateInfo = entry.Entity;
        entry.State = StateHelpers.ConvertState(stateInfo.State);
    }
}  

状態をEFに戻す関数:

public static EntityState ConvertState(State state)
{
    switch (state)
    {
        case State.Added:
            return EntityState.Added;
        case State.Modified:
            return EntityState.Modified;
        case State.Deleted:
            return EntityState.Deleted;
        default:
            return EntityState.Unchanged;
    }
}

彼のリストBasicUserを使用して新しいAdminUserを追加する場合、すべてが問題なく正常に機能します。EFBasicUser AdminUserを変更して、BasicUserの更新を生成するが、外部キーがnullであるという条件を追加すると、問題が発生します。

ここでは、生成された2つの更新を確認できます

AdminUser:

 exec sp_executesql N'update [dbo].[User]
set [Name] = @0, [LastName] = @1, [Email] = @2
where (([Id] = @3) and ([RowVersion] = @4))
select [RowVersion]
from [dbo].[User]
where @@ROWCOUNT > 0 and [Id] = @3',N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 nvarchar(max) ,@3 int,@4 binary(8)',@0=N'Beto',@1=N'Guerere',@2=N'beto@gmail.com',@3=3,@4=0x0000000000000801

基本的なユーザー:

exec sp_executesql N'update [dbo].[User]
set [Name] = @0, [LastName] = @1, [Position] = @2, [Department] = @3, [AdminUser_Id] = @4
where ((([Id] = @5) and ([RowVersion] = @6)) and [AdminUser_Id] is null)
select [RowVersion]
from [dbo].[User]
where @@ROWCOUNT > 0 and [Id] = @5',N'@0 nvarchar(max) ,@1 nvarchar(max) ,@2 nvarchar(max) ,@3 nvarchar(max) ,@4 int,@5 int,@6 binary(8)',@0=N'Viomar',@1=N'Guerere',@2=N'Supervisora',@3=N'Ventas',@4=3,@5=4,@6=0x0000000000000802

BasicUserの更新を行うためのEF生成SQLコマンドに見られるように、レコードの条件がAdminUser_IdにNull値を持っていることが追加されます。その理由がわかりません。そのユーザーはスーパーバイザーに割り当てられているため、フィールドをnullにすることはできません。

説明したいと思います。

あなたが私に与えることができるどんな助けにも感謝します。

4

2 に答える 2

0

すでに管理者が割り当てられているbasicuserを取得していますか?adminuseridを取得してから更新するまで、adminuseridが保持されていないように見えます。これは、たとえば、その外部キーを表示したくないためにビューに含めないMVCアプリケーションでよく見られます。ただし、オブジェクトを更新してコントローラーに送信すると、nullFKを持つ新しいユーザーインスタンスが作成されます。また、そのFKを同時実行チェックフィールドとして使用しているため、コントローラーからビュー、コントローラーに移動するときに値を保持することが二重に重要です。この場合、幸いなことに、私はすでにこの問題に関するブログ投稿を持っているので、ここで完全に再説明する必要はありません。http://thedatafarm.com/blog/data-access/round-tripping-a-timestamp-field-with-ef4-1-code-first-and-mvc-3/

それが事実かどうか教えてください。もしそうなら、うまくいけばそれはあなたの問題を解決します。そうでない場合は、おそらくもっと質問があります!:)

(psコードの残りの部分はかなりおなじみのようです!:)それは私の&RowanのDbContextに関する本から来ていますか?:))

于 2012-11-13T16:41:41.843 に答える
0

私への私の質問への回答:EFは、データベース内のFKを、モデル内でこのフォームの変数として操作する必要があると考えています。切断して作業する場合は、この情報が確実に保存されるようにする必要があります。

最初に行う必要があるのは、BasicUserクラスに、AdminUser_Idと呼ぶint型の変数を追加することです。

public class BasicUser: User
    {       
        public String Position { get; set; }
        public String Department { get; set; }
        public int AdminUser_Id { get; set; }
    }

次に、追加された変数がAdminUser AdminUserを参照するFKであり、多くのBasicUserを持つことができることをEFに通知する必要があります。

これを行うには、コンテックスを宣言している場所、DataLayer(私の場合)に移動し、これが作成されている場所で、次のアノテーションを追加します。

modelBuilder.Entity<AdminUser>()HasMany(A => A.UsersList ).WithRequired().HasForeignKey(B => B.AdminUser_Id );

We update the model and with these adjustments the mistake is eliminated completely at the moment of realizing the update of the record.

FKとEFの詳細については、次の記事を読むことをお勧めします。

  1. 存在しない外部キーを処理する
  2. コードファーストリレーションシップFluentAPI

特にJulieLermanにご協力いただき、誠にありがとうございます。それがなければ、その解決策にたどり着くまでにもう少し費用がかかりました。

説明したと思います。

于 2012-11-20T14:38:45.837 に答える