2011-08-18 15 views
6

データベースに保存する前にエンティティの更新に関する問題を解決して、奇妙な動作をしました。Entity Frameworkの奇妙なエンティティをコードファーストで更新する

私はASP.NET MVC 3 WebアプリケーションでEntity Framework 4.1 Code-Firstを使用しています。ここにモデルです:

public class Order 
{ 
    public int OrderId { get; set; } 
    public int CarId { get; set; } 
    public DateTime BeginRentDate { get; set; } 
    public DateTime EndRentDate { get; set; } 
    public decimal RentPrice { get; set; } 
    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    public int CarId { get; set; } 
    public string Brand { get; set; } 
    public string Model { get; set; } 
    public string NumberPlate { get; set; } 
    public decimal RentPrice { get; set; } 
} 

各車にはRentPriceがあります。この価格は、作成時にOrderのRentPriceにコピーする必要があります。車は、私は価格の値をコピーしたいOrder.RentPriceはここで0

あるので、最初は、ユーザによって選択された:それは実体が検証エラーを持っているSaveChangesにエラーのために働いていない

[HttpPost] 
public ActionResult Create(Order order) 
{ 
    order.RentPrice = _context.Cars.Find(order.CarId).RentPrice; 

    if (ModelState.IsValid) 
    { 
     _context.Orders.Add(order); 
     _context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(order); 
} 

。 OK。最初にUpdateModel(order);に電話して値を変更する必要があることがわかりました。

だから私は何を持っています。ワーキングコード:

_context.Orders.Add(order); 
UpdateModel(order); 
order.RentPrice = 777; 
_context.SaveChanges(); 

ない作業コード:

_context.Orders.Add(order); 
UpdateModel(order); 
order.RentPrice = _context.Cars.Find(order.CarId).RentPrice; 
_context.SaveChanges(); 

動作するコードは(!):

_context.Orders.Add(order); 
UpdateModel(order); 
var t = (double)_context.Cars.Find(order.CarId).RentPrice; 
order.RentPrice = (decimal)t; 
_context.SaveChanges(); 

は、誰かが説明でき、ここで何が起こっているしてください?特にのマジックは、最後のコードブロックの3行目と4行目にあります。

更新

私はDbEntityValidationExceptionを取得しています:「検証は、1つのまたは複数のエンティティのために失敗した詳細は、 『EntityValidationErrors』プロパティを参照してください。」 内部例外から: "OriginalValuesは、追加状態のエンティティには使用できません。"

+1

order.RentPrice = _context.Cars.Find(order.CarId).RentPrice;の最後に2つのセミコロンがあることに気付きましたか? - >コードの最後のブロックの隣で? – Jack

+1

SaveChangesメソッドの検証エラーは何ですか?あなたの最初のCreateメソッドのコードはうまく動作します。 – agradl

+0

@Jack、ポストを書いている間にちょうどタイプミス。一定。 –

答えて

0

どこにでもプライマリキーを宣言しましたか?この

builder.Entity<Car>().HasKey(x=>x.CarId); 
builder.Entity<Order>().HasKey(x=>x.OrderId); 
+0

EFは設定よりも規則を使用しています(これにはIdプロパティが必要です)。だから、私のデータベースには主キーがあります。私がチェックしました。どのようにそのコードの最後のブロックを説明しますか? –

0

のように、私はアイデアを持っているが、それはだ、

public class Order 
{ 
    [Key] 
    public int OrderId { get; set; } 
    public int CarId { get; set; } 
    public DateTime BeginRentDate { get; set; } 
    public DateTime EndRentDate { get; set; } 
    public decimal RentPrice { get; set; } 
    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    [Key] 
    public int CarId { get; set; } 
    public string Brand { get; set; } 
    public string Model { get; set; } 
    public string NumberPlate { get; set; } 
    public decimal RentPrice { get; set; } 
} 

またはあなたのコンテキストでは、キーを宣言するために流暢APIを使用することができます:あなたはこのようFluentAPIを使用して、または属性のいずれかのことを行う必要がありますより多くの推測...あなたがそのCreate関数に入るときには、コンテキストはすでにそのOrderを知っているでしょうか?もしそうなら、それを再度追加しようとすると、そのエラーが出る可能性があります。

最後のコード(驚くべきことに動作するコード)では、2倍にキャストせずに中間のvarを使用しようとしましたか?

私はそのUpdateModelにも興味を持っています...私はEFを使用していますが、MVCを使用していないので多分それについて何もしていませんが、それがカスタム関数なら何ですか?あなたが得るとき

18

は「検証は、一の以上のエンティティに失敗しました。詳細については 『EntityValidationErrors』プロパティを参照してください。「インナー 例外から: 『OriginalValuesが追加 状態のエンティティのために使用することはできない』

それは、このような空白または他の制約た、NOT NULL collumnsなどのエラーがあったことにより、エンティティ検証エラーを確認してください。デバッグや

try{ 
... 
catch (DbEntityValidationException ex) 
    { 
foreach (var validationErrors in ex.EntityValidationErrors) 
    { 
    foreach (var validationError in validationErrors.ValidationErrors) 
    { 
     System.Diagnostics.Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); 
    } 
    } 
} 
+0

質問の私のコード例を読んだことがありますか? –

+0

こんにちはごめんなさいあなたの元の質問についての説明はありません。そのヒントは本当にDbEntityValidationExceptionから来ているのですか? – John

+0

私のケースでは、レジスタビューモデルとアイデンティティモデルの間に不一致のデータアノテーションが見つかりました。 – Dreamcasting

0

のように、私はとっくの昔整流されていた問題は、ちょうど私の2セントを貢献することを望んでいたと確信しています。

私も同じエラーメッセージの問題に走った、私はOracleを使用していましたEF 5.0。フィン私は12時間以上を無駄にして解決策を得ました。

私には、値を挿入しようとしていたテーブルのユーザーのアクセス許可が不足していました。エラーメッセージには、本当に奇妙な実際のアクセス許可の問題のヒントはありませんでした。

誰かがこの機能を見つけて、トラブルシューティングで私のような時間を無駄にしないようにしてください。

乾杯、

アビ

1

OriginalValuesが追加された状態でのエンティティのために使用することはできません。

がモデルでを発生させないよう非アイデンティティプライマリキーフィールドが指定されていることを確実にすることによって補正することができます。

エラーは、コンテキストがある場合は実際には説明になりますが、それ以外の場合はわかりません。データベースは、挿入のための2つの文を生成し、第二には、次のとおりです。

SELECT [PrimaryKeyId] 
FROM [dbo].[Entity] 
WHERE @@ROWCOUNT > 0 AND [PrimaryKeyId] = scope_identity() 
/* SP:StmtCompleted... */ 

この文は、非アイデンティティの列の任意の行を返しません。したがって、OriginalValuesは追加された状態で変更されません。これは、影響を受ける行の数が既存の変更されたデータを検出するために使用されるため、この例外がOptimisticConcurrencyExceptionにラップされている理由についても説明します。

関連する問題