2012-03-07 13 views
5

現在、EF4.3およびコード・ファーストを使用しています。私のオブジェクトの作成は、(私の見解では、自動生成されたCreateを使用して)動作しますが、オブジェクトを編集しようとすると、究極的にナビゲーションプロパティに結びつく変更は保存されません。私はreading on relationshipsでしたが、関係が変更されたことを私のコンテキストに伝える方法を理解していません。エンティティ・フレームワーク内のナビゲーション・プロパティを更新するための関係を取得できません

私の実装のコード例です。ここ

@* Snippet from my view where I link into my ViewModel. *@ 
<div class="row"> 
    <div class="editor-label"> 
     @Html.LabelFor(model => model.ManagerID) 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownListFor(model => model.ManagerID, ViewBag.Manager as SelectList, String.Empty) 
     @Html.ValidationMessageFor(model => model.ManagerID) 
    </div> 
</div> 

は私のコントローラの実装(私の編集のPOST)である:私のプロジェクトオブジェクト内

[HttpPost] 
    public ActionResult Edit(ProjectViewModel projectViewModel) 
    { 
     if (ModelState.IsValid) 
     { 
      Project project = new Project(); 
      project.ProjectID = projectViewModel.ProjectID; 
      project.Name = projectViewModel.Name; 
      project.ProjectManager = repository.GetUser(projectViewModel.ManagerID); 
      repository.InsertOrUpdateProject(project); 
      repository.Save(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.Manager = new SelectList(repository.GetUsers(), "UserID", "FullName", projectViewModel.ManagerID); 
     return View(projectViewModel); 
    } 

:ここ

public class Project 
{ 
    public int ProjectID { get; set; } 
    [Required] 
    public string Name { get; set; } 

    // Navigation Properties 
    public virtual User Manager { get; set; } 
} 

リポジトリから対応する方法である(ここで、私のコンテキスト常駐):

public void InsertOrUpdateProject(Project project) 
    { 
     if (program.ProjectID == default(int)) 
     { 
      context.Projects.Add(project); 
     } 
     else 
     { 
      context.Entry(project).State = EntityState.Modified; 
     } 
    } 

これは私のプロパティを更新するためには機能しますが、ナビゲーションプロパティ(この場合はManager)は更新されません。助けをお待ちしています。

答えて

11

状態をModifiedに設定すると、ナビゲーションプロパティではなく、変更されたスカラープロパティのみがマークされます。あなたは、いくつかのオプションがあります。

  • ハック(あなたがそれを好きではないだろう)

    //... 
    else 
    { 
        var manager = project.Manager; 
        project.Manager = null; 
        context.Entry(project).State = EntityState.Modified; 
        // the line before did attach the object to the context 
        // with project.Manager == null 
        project.Manager = manager; 
        // this "fakes" a change of the relationship, EF will detect this 
        // and update the relatonship 
    } 
    
  • は(熱心ロード)現在のマネージャなど、データベースからプロジェクトをリロードしてください。次に、プロパティを設定します。変更の追跡は、マネージャの変更を再度検出し、UPDATEを書き込みます。

  • モデル内Managerナビゲーションプロパティのために外部キープロパティを公開:今すぐ

    ​​

    ManagerIDはスカラプロパティで、Modifiedに状態を設定すると、このプロパティが含まれます。

    Project project = new Project(); 
    project.ProjectID = projectViewModel.ProjectID; 
    project.Name = projectViewModel.Name; 
    project.ManagerID = projectViewModel.ManagerID; 
    repository.InsertOrUpdateProject(project); 
    repository.Save(); 
    
    は、いくつかのオプションがここにあります
+0

優秀への更新をチェックアウトしてください。ありがとうございました。もともと私は外来キールートを行っていましたが、いくつか問題がありました。それはうまくいきましたが、適切にマッピングするためのすべてのナビゲーションプロパティで[ForeignKey( "Name")]属性を定義しなければなりませんでした。あなたの答えを受け入れる。ありがとう! – glockman

+0

@ user1240560:私の答えの名前では、実際にForeignKey属性(名前の規則でFK検出)なしで動作するはずです。しかし、あなたの名前がはっきりと違っていて、大会のルールに従わなければ、あなたは注釈が必要です。 – Slauma

+0

@Slauma私はあなたを愛していますが、他のアプローチはコードファーストモデルではうまくいくはずですが、データベースで最初に私のために働く唯一のものはあなたのハックでした、私は数日間それを乱していました、そして今私はあなたはあまりにも –

-2

ナビゲーションプロパティの意味を正確にはわかりません。外資系の関係のような意味ですか?そうであれば、次のデータ注釈を試してください:

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [ForeignKey("YourNavigationProperty")] 
    public virtual UserManager { get; set; } 
} 

あなたのEFコンテキストを更新して、何が起こるかを見てください。

UPDATE

public class Project 
{ 
    public int ProjectID { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [ForeignKey("ManagerId")] 
    public ManagerModel UserManager { get; set; } 
} 

public class ManagerModel 
{ 
    [Key] 
    public int ManagerId { get; set; } 

    public String ManagerName { get; set; } 
} 

それが動作するかどうか?

+0

私は明示的に自分のFK名を定義しません。私はマネージャーの値を新しいマネージャ(動作するようです)に設定できるようにしたいのですが、SaveChanges()を呼び出すと、変更は実際にはデータベースに保存されません。私はそれがどうなるかわからない。 – glockman

+0

私の答え – jacqijvv

2

、私はそれらの3が一覧表示されます。また、あなたはちょうどあなたがあなたのビューから取得IDを割り当てることができ、データベースからManagerユーザーをロードする必要はありません。

オプション1:

GraphDiff

を使用するには、*これがtrueに設定され、あなたのコンテキストのConfiguration.AutoDetectChangesEnabled必要があります。ただ、NuGet

GraphDiffの詳細については
Install-Package RefactorThis.GraphDiff 

その後

using (var context = new Context()) 
{ 
    var customer = new Customer() 
    { 
     Id = 12503, 
     Name = "Jhon Doe", 
     City = new City() { Id = 8, Name = "abc" } 
    }; 

    context.UpdateGraph(customer, map => map.AssociatedEntity(p => p.City)); 
    context.Configuration.AutoDetectChangesEnabled = true; 

    context.SaveChanges(); 
} 

でGraphDiffをインストール

hereを見て。

オプション2:検索および編集

コンテキストにそれを追跡するために、EFを使用してエンティティを検索します。次に、プロパティを編集します。

*これにより、コンテキストのConfiguration.AutoDetectChangesEnabledがtrueに設定されている必要があります。

var customer = new Customer() 
{ 
    Id = 12503, 
    Name = "Jhon Doe", 
    City = new City() { Id = 8, Name = "abc" } 
}; 

using (var context = new Contexto()) 
{ 
    var customerFromDatabase = context.Customers 
             .Include(x => x.City) 
             .FirstOrDefault(x => x.Id == customer.Id); 

    var cityFromDataBase = context.Cities.FirstOrDefault(x => x.Id == customer.City.Id); 

    customerFromDatabase.Name = customer.Name; 
    customerFromDatabase.City = cityFromDataBase;     

    context.Configuration.AutoDetectChangesEnabled = true; 
    context.SaveChanges(); 
} 

オプション3:これが最善の方法ですが、データベース上の懸念と、それは混乱あなたのクラスのパフォーマンスの問題では、スカラプロパティに

を使用します。 Idをマップするスカラー(プリミティブタイプ)プロパティを作成する必要があるためです。

※このように、Configuration.AutoDetectChangesEnabledをtrueに設定する必要はありません。また、エンティティを取得するためにデータベースへのクエリを行う必要もありません(最初の2つのオプションがあります - はい、GraphDiffは裏でそれを行います)。

var customer = new Customer() 
{ 
    Id = 12503, 
    Name = "Jhon Doe", 
    City_Id = 8, 
    City = null 
}; 

using (var contexto = new Contexto()) 
{ 
    contexto.Entry(customer).State = EntityState.Modified; 
    contexto.SaveChanges(); 
} 
関連する問題