codefirst Entity Framework で多くの問題が発生しています。
と の 2 つのテーブルを持つデータベースがありUsers
ますCountries
。Users
の外部キーを持つフィールドがありますCountryId
。ユーザーが最初にデータベースに追加されると、FK が正常に更新されます。ただし、新しい DbContext にアタッチするユーザーの FK を更新しようとしても、変更は行われません。
最初にユーザーを作成したコンテキストで FK を更新できます。また、データベースからユーザーを取得するコンテキストで FK を更新できます。ただし、Attach
ユーザーだけのコンテキストでは、通常のフィールドnvarchar
またはint
フィールドが更新されても、FK フィールドは更新されません。
ここに私のDbContextがあります:
class DataContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Country> Countries { get; set; }
}
そして、ここに私のモデルがあります:
public class User
{
public int UserId { get; private set; }
public string Name { get; set; }
public virtual Country Country { get; set; }
}
public class Country
{
public int CountryId { get; private set; }
public string Name { get; set; }
}
このメソッドは、問題を示しています。データベースに 3 人のユーザーを追加し、3 つの異なる方法でそれらを変更しようとしました。ユーザーが追加された元のコンテキスト、Attach
.変更:
static void Main(string[] args)
{
Country[] countries;
using (var dc = new DataContext())
{
countries = dc.Countries.ToArray();
}
var u = new User();
// FIRST ROW
using (var dc = new DataContext())
{
u.Name = "First";
u.Country = countries[0];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Added;
dc.SaveChanges();
u.Name = "FirstChanged";
u.Country = countries[1];
// defaults to 'added' once u is tracked.
dc.Entry(countries[1]).State = EntityState.Unchanged;
dc.SaveChanges();
}
// SECOND ROW
u = new User();
using (var dc = new DataContext())
{
u.Name = "Second";
u.Country = countries[0];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Added;
dc.SaveChanges();
}
using (var dc = new DataContext())
{
u.Name = "SecondChanged";
u.Country = countries[1];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Modified;
dc.SaveChanges();
}
// THIRD ROW
u = new User();
using (var dc = new DataContext())
{
u.Name = "Third";
u.Country = countries[0];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Added;
dc.SaveChanges();
}
using (var dc = new DataContext())
{
u = dc.Users.Find(u.UserId);
u.Name = "ThirdChanged";
u.Country = countries[1];
dc.Entry(countries[1]).State = EntityState.Modified;
dc.SaveChanges();
}
}
このアプリケーションは、データベースで次の結果を生成します。
UserId Name Country_CountryId
------------------------------------------------------------------------
1 FirstChanged 2
2 SecondChanged 1
3 ThirdChanged 2
ご覧のとおり、すべてのケースName
で正常に更新されました。最初のケースと 3 番目のケースでは、CountryId
が更新されます。ただし、2 番目のケースでは、CountryId は更新されません。残念ながら、DataContext の外部でユーザーが編集するためにモデルを永続化できるようにしたいので、これは私にとって最も関連性の高いケースです。
なぜこれが起こっているのかわかりません.Name
フィールドが更新されなかった場合は理解できましたが、そのCountryId
理由はわかりません. どちらの場合も、Country
オブジェクトは追跡され、 としてマークされUnchanged
ます。2番目のケースだけが機能しない理由がわかりません。
ここに何があるかを理解するのを手伝ってください。私が考えることができる唯一の解決策は、変更する必要があるときに3番目のケースを使用することです.保存すると、永続化されたオブジェクトから保存されたデータベースから取得された新しいオブジェクトにデータをコピーします...しかし、明らかにこれはばかげた解決策。
以下に、この問題を示すコンソール アプリケーションを示します。それを実行するには、NuGet (または同様のもの) と次のような接続文字列を使用して EntityFramework を取得する必要があります。
<add name="DataContext" connectionString="DataSource=.\DataContext.sdf" providerName="System.Data.SqlServerCe.4.0" />
コード:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Country[] countries;
using (var dc = new DataContext())
{
countries = dc.Countries.ToArray();
}
var u = new User();
// FIRST ROW
using (var dc = new DataContext())
{
u.Name = "First";
u.Country = countries[0];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Added;
dc.SaveChanges();
u.Name = "FirstChanged";
u.Country = countries[1];
// defaults to 'added' once u is tracked.
dc.Entry(countries[1]).State = EntityState.Unchanged;
dc.SaveChanges();
}
// SECOND ROW
u = new User();
using (var dc = new DataContext())
{
u.Name = "Second";
u.Country = countries[0];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Added;
dc.SaveChanges();
}
using (var dc = new DataContext())
{
u.Name = "SecondChanged";
u.Country = countries[1];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Modified;
dc.SaveChanges();
}
// THIRD ROW
u = new User();
using (var dc = new DataContext())
{
u.Name = "Third";
u.Country = countries[0];
dc.Users.Attach(u);
dc.Entry(u).State = System.Data.EntityState.Added;
dc.SaveChanges();
}
using (var dc = new DataContext())
{
u = dc.Users.Find(u.UserId);
u.Name = "ThirdChanged";
u.Country = countries[1];
dc.Entry(countries[1]).State = EntityState.Modified;
dc.SaveChanges();
}
}
}
class DataContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Country> Countries { get; set; }
public DataContext()
{
Database.SetInitializer<DataContext>(new ModelInitializer());
Database.Initialize(false);
}
}
class ModelInitializer : DropCreateDatabaseAlways<DataContext>
{
protected override void Seed(DataContext context)
{
var jsds = new List<Country>
{
new Country("United Kingdom"),
new Country("United States Of America")
};
jsds.ForEach(jsd => context.Countries.Add(jsd));
}
}
public class User
{
public int UserId { get; private set; }
public string Name { get; set; }
public virtual Country Country { get; set; }
}
public class Country
{
public int CountryId { get; private set; }
public string Name { get; set; }
public Country() { }
public Country(string name)
{
Name = name;
}
}
}
この質問をご覧いただきありがとうございます。私はそれを修正しようとして2日目ですが、ゆっくりと夢中になっています...