は、この単純なモデルとのViewModelシナリオを考えデータベースから取り出します。フォームが送信されたときに今、私が行いますエンティティフレームワーク4.1最初のコードと自動マッパーの問題
SomeModel destinationModel = someContext.SomeModel.Include("Company").Where(i => i.Id == id) // assume id is available from somewhere.
その後、私は
Company oldCompany = destinationModel.company; // save it before mapper assigns it null
Mapper.Map(sourceViewModel,destinationModel);
//After this piece of line my company in destinationModel will be null because sourceViewModel's company is null. Great!!
//so I assign old company to it
destinationModel.company = oldCompany;
context.Entry(destinationModel).State = EntityState.Modified;
context.SaveChanges();
、問題を行う、私はそれがSaveChangesメソッドの後にデータベースにまだnullである私の会社にoldCompanyを割り当てる場合もあります。
注:
私はこれらの行に変更した場合:これらの
destinationModel.company = oldCompany;
context.Entry(destinationModel).State = EntityState.Modified;
context.SaveChanges();
:私は状態を2回変更
context.Entry(destinationModel).State = EntityState.Modified;
destinationModel.company = oldCompany;
context.Entry(destinationModel).State = EntityState.Modified;
context.SaveChanges();
お知らせし、それが正常に動作します。何が問題なの?これはef 4.1バグですか?
この問題に対処するためのサンプルコンソールアプリケーションです:
using System;
using System.Linq;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using AutoMapper;
namespace Slauma
{
public class SlaumaContext : DbContext
{
public DbSet<Company> Companies { get; set; }
public DbSet<MyModel> MyModels { get; set; }
public SlaumaContext()
{
this.Configuration.AutoDetectChangesEnabled = true;
this.Configuration.LazyLoadingEnabled = true;
}
}
public class MyModel
{
public int Id { get; set; }
public string Foo { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
public int? CompanyId { get; set; }
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MyViewModel
{
public string Foo { get; set; }
public Company Company { get; set; }
public int? CompanyId { get; set; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer<SlaumaContext>(new DropCreateDatabaseIfModelChanges<SlaumaContext>());
SlaumaContext slaumaContext = new SlaumaContext();
Company company = new Company { Name = "Microsoft" };
MyModel myModel = new MyModel { Company = company, Foo = "Foo"};
slaumaContext.Companies.Add(company);
slaumaContext.MyModels.Add(myModel);
slaumaContext.SaveChanges();
Mapper.CreateMap<MyModel, MyViewModel>();
Mapper.CreateMap<MyViewModel, MyModel>();
//fetch the company
MyModel dest = slaumaContext.MyModels.Include("Company").Where(c => c.Id == 1).First(); //hardcoded for demo
Company oldCompany = dest.Company;
//creating a viewmodel
MyViewModel source = new MyViewModel();
source.Company = null;
source.CompanyId = null;
source.Foo = "foo hoo";
Mapper.Map(source, dest); // company null in dest
//uncomment this line then only it will work else it won't is this bug?
//slaumaContext.Entry(dest).State = System.Data.EntityState.Modified;
dest.Company = oldCompany;
slaumaContext.Entry(dest).State = System.Data.EntityState.Modified;
slaumaContext.SaveChanges();
Console.ReadKey();
}
}
}
'CompanyModel'や' SomeViewModel'に 'CompanyI'のような外部キープロパティがあります。 ?あなたのViewModelに 'null'が入っていることが分かったら、' Include'を使って 'Company'を読み込むのはなぜですか?私の意見では、 'Include'を削除することができます。 – Slauma
外部キーのプロパティはNULL可能であり、 'SomeViewModel'にもありますか? 'Mapper.Map'の後で何が起こりますか?' destinationModel'のFK値を上書きしますか? – Slauma
@Slauma:はい、あなたはかなり正しいです。外部キーはNULL可能です。はい、Mapper.Mapの後にfkの値はnullですが、明示的に値を代入しますが、効果はありません。それはヌルだけを「好き」でした。 – Jaggu