2012-12-31 7 views
6

添付ファイルを使用してEF 5.xを使用してテーブルの更新を実行しようとしています。このテーブルには、必要な他のフィールドがありますが、既存の行があります。だから私はフェッチせずに更新しようとしています。 useridはテーブルの主キーです。私はステータスを更新しようとしています。それはEntityValidationErrorsをスローします。これはパスワードが必須であり、これは必須のフィールドで、プライマリキーではありません。これは既存の行の更新であるため、なぜ更新するためにrequriedフィールドを提供する必要がありますか?Update Entity Frameworkへのアタッチ

var webUser = new WebUser() { UserId = webUserId, OnlineStatus = (sbyte)status }; 
    using (var dbxupdate = new xEntities()) 
    { 
     try 
     { 
      dbxupdate.WebUsers.Attach(webUser); 
dbxupdate.Entry(webUser).State = EntityState.Modified; 
      dbxupdate.Entry(webUser).Property(x => x.OnlineStatus).IsModified = true; 
      dbxupdate.SaveChanges(); 
     } 
     catch (DbEntityValidationException dbEx) 
     { 
      foreach (var validationErrors in dbEx.EntityValidationErrors) 
      { 
       foreach (var validationError in validationErrors.ValidationErrors) 
       { 
        Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); 
       } 
      } 
     } 
    } 
+0

最初の行では、新しい 'webUser'を作成していて、データベースから取得していません。ブレークポイントを設定し、 'webUser's'パスワードが' null'でないかどうか確認してください。 – Yoav

+0

データを取得しませんでした。私は更新を行うつもりだったので、私は既にプライマリキーを持っています –

答えて

1

エンティティフレームワークでは、他のフィールドに適切な値を設定せずにフィールドを更新できません。したがって、あなたの仕事にストアドプロシージャを使用する方が良いです。もう1つの方法は、レコードをフェッチしてフィールドを更新することです。

+1

dbxupdate.Configuration.ValidateOnSaveEnabled = falseを設定すると、http://stackoverflow.com/a/33121240/2353894のように保存時の検証を無効にすることができます。 – nhkhanh

+0

汚れていて最適なソリューションです。 EFを使用して既存のテーブルを更新しようとすると、多くの問題に直面する可能性があります。 – Jacob

2

エンティティは、データベースに接続されているか、データベースからロードされているかにかかわらず、保存時に検証されます。検証属性または検証メソッドを使用する場合、エンティティは保存される検証を渡す必要があります。

パスワードフィールドに[Required]属性がある場合は、あなたは非常に固執していると思います。エンティティを読み込んだ後、単に情報を追加するのではなく、情報を更新する必要があります。

+0

私はそのデータ属性を持っていません。 Dbレベルでは必須ですがEFでは必要ありません.ADO.netはdbからその属性を取得したと思います。私は生成されたコードにその属性が表示されません –

+0

私はこれを行うためにSPを作成する必要があるように見えます。 –

+0

エンティティ全体を最初にロードせずにレコードの一部だけを更新する場合は、おそらくSPが良い方法でしょう。 –

0

これを試してみてください(using文の中の場所この)との最初の行を置き換える
var wu = dbxupdate.webUsers.single(i=>i.id== webUserId);
wu.OnlineStatus = whatever;

コードが続く...あなたはそれのインスタンスを取得する必要がありますエンティティを更新するために。それ以外の場合は、宣言されていないプロパティの値がnullになります。

14

.Attach()は、このようなデタッチシナリオ内のエンティティを更新するため、実際にのみ有用である:あなたのシナリオでは

User entity = null; 

using (var db = new DbContext()) 
{ 
    entity = (from p in db.Users 
       where p.id == 1 
       select p).FirstOrDefault(); 

    System.Diagnostics.Trace.WriteLine(entity.Name); //Outputs "Jane Doe" 
} 

entity.Name = "John Doe" //Modified while no longer connected to database 

using (var db = new DbContext()) 
{ 
    db.Users.Attach(entity); 
    db.Entry(entity).Property(a => a.Name).IsModified = true; 
    db.SaveChanges(); 

    System.Diagnostics.Trace.WriteLine(entity.Name); //Now outputs "John Doe" 
} 

あなたが作成しているエンティティは、それがキーだとデータベースのようにそれを処理されることにより、取得されていません全く新しい存在です。私は、あなたのパスワードがnull不可能なフィールドであると仮定しているので、変更を保存しようとするとEFがエラーをスローします。このようなエラーがなければ、EFはあなたが変更していないフィールドを自動的に無効にしてから、エンティティを保存します(探している結果ではありません)。その後、

using (var db = new DbContext()) 
{ 
    db.Users.Single(a => a.id == 1).OnlineStatus = (sbyte)status; 
    db.SaveChanges 
} 

そして、あなたがしたい他のどんなエラー処理/検証コードを追加します。そして、あなたはおそらく、次のような何かを行う必要があるでしょう、あなたが探しているの変更を行うためには

。あるいは、一度に複数のフィールドに変更を加えるために、エンティティを変数に格納することもできます。 EFはどの値が変更されたかを自動的に判断し、変更を行うために必要なSQLのみを生成する必要があります。私が間違っている場合

foreach (var item in entityList) 
{ 
    var entity = db.Users.Single(a => a.id == item.id); 

    entity.Name = item.Name; 
    entity.Address = item.Address; 
} 

誰かが私を修正しますが、EFはエンティティのみ/実際にこのコードの影響を受けているフィールドを更新する必要があります:あなたはのようなものを持っている場合があることを意味します。名前またはアドレスが同じままである場合、EFはデータベースに変更を保存するときにそのエンティティのそのフィールドをスキップします。