私はEFCodeFirstを使用しており、次のように2つのクラスが定義されています。
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}
[Table("Visitors")]
public class Visitor : User
{
public Visitor()
{
Favourites = new List<Building>();
}
public virtual IList<Building> Favourites { get; set; }
}
これは、Table-Per-Type継承を使用し、DBスキーマを次のように定義します。
Users Table
Id int PK
Username nvarchar(max)
Email nvarchar(max)
Visitors Table
Id int PK (FK to Users table)
これはまさに私がそれを構造化するために望んでいた方法です。ここで私の質問は、Userオブジェクトを作成してDBに保存した場合、後でそれを訪問者に拡張するにはどうすればよいですか(必要な場合)。ユーザーを削除して新しい訪問者を作成する必要がありますか?または、ユーザーをビジターオブジェクトにキャストすると、ユーザーテーブルのエントリがそのまま残り、ユーザーを参照する新しいエントリがビジターテーブルに追加されますか?以下のコードのようなものですか?
Context.Set<User>().Add(new User(){Id=1, Username="Bob", Email="bob@mail.bob"});
Context.SaveChanges();
//and elsewhere in the project I want to do this sort of thing:
Context.Set<Visitor>().Where(v=>v.Id == 1).FirstOrDefault().Favourites.Add(someFavouriteBuilding); //This obviously doesn't work, because the FirstOrDefault call returns null, so it will throw an exception
Context.SaveChanges();
//or maybe this can be modified slightly to work?:
var visitor = Context.Set<Visitor>().Where(v=>v.Id == 1).FirstOrDefault();
if (visitor==null)
{
visitor = new Visitor(Context.Set<User>().Where(u=>u.Id == 1).FirstOrDefault()); // this contructor copies all the property values accross and returns a new object
}
visitor.Favourites.Add(someFavouriteBuilding); //This obviously doesn't work either
var entry = Context.Entry(visitor);
entry.State = EntityState.Modified;//here it throws this error: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
Context.SaveChanges();
上記のコードの2番目のアプローチは、コンテキストに正しくアタッチすることしかできない場合に機能すると思います。とにかく、上記のコードは、私が達成しようとしていることを示すためだけのものです。私はそれが機能しないことを知っています。誰かがもっとエレガントなアプローチを提案できますか?
ありがとうございました