gpt4 book ai didi

c# - 将 EF CodeFirst 基类转换为继承类(使用 table-per-type)

转载 作者:太空狗 更新时间:2023-10-29 22:23:26 24 4
gpt4 key购买 nike

我正在使用 EF Code First 并定义了两个类,如下所示:

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 继承并定义数据库架构如下:

Users Table
Id int PK
Username nvarchar(max)
Email nvarchar(max)
Visitors Table
Id int PK (FK to Users table)

这正是我想要的结构。 现在我的问题是,如果我创建一个 User 对象并将其保存到数据库中,我以后如何才能将其扩展为一个 Visitor(如果我需要的话?)我是否需要删除用户并创建一个新的访问者,或者我可以如何将用户转换为访问者对象并且用户表中的条目将保持不变并且新条目将添加到引用用户的访问者表中?类似于下面的代码?

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();

我认为,如果我只能将其正确附加到上下文,则上述代码中的第二种方法可能会奏效。无论如何,上面的代码只是为了向您展示我正在努力实现的目标。我知道这是行不通的。谁能建议更优雅的方法?

谢谢

最佳答案

几乎在那里...关键是分离现有实体,然后附加新实体。

这是一个例子:

using System.Data;
using System.Data.Entity;
using System.Diagnostics;

public class Animal
{
public long Id { get; set; }
}

public class Dog : Animal
{
}

public class AnimalsContext : DbContext
{
public DbSet<Animal> Animals { get; set; }
}


public class Tester
{
public void Test()
{
var context = new AnimalsContext();


var genericAnimal = new Animal();
context.Animals.Add(genericAnimal);
context.SaveChanges();


// Make a new clean entity, but copy the ID (important!)
var dog = new Dog { Id = genericAnimal.Id, };

// Do the old switch-a-roo -- detach the existing one and attach the new one
// NOTE: the order is important! Detach existing FIRST, then attach the new one
context.Entry(genericAnimal).State = EntityState.Detached;
context.Entry(dog).State = EntityState.Modified;
context.SaveChanges();


var thisShouldBeADog = context.Animals.Find(genericAnimal.Id);

// thisShouldBeADog is indeed a Dog!
Debug.Assert(thisShouldBeADog is Dog);

// And, of course, all the IDs match because it's the same entity
Debug.Assert((genericAnimal.Id == dog.Id) && (dog.Id == thisShouldBeADog.Id));
}
}

关于c# - 将 EF CodeFirst 基类转换为继承类(使用 table-per-type),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12843678/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com