用例示例
用户已在网站上注册(向“用户”表添加记录)。然后转到电子邮件并确认注册。确认链接重定向到具有人员编辑表单的页面,用户填写表单并提交表单(将记录添加到人员表)。
技术说明
我在EF模型中定义了一个简单的2对象Table-Per-Type继承。
的实体 的
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
public class Person : User
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
的数据库 的
public class MainDataContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Person> Persons { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var configs = modelBuilder.Configurations;
configs.Add(new UserConfiguration());
configs.Add(new PersonConfiguration());
}
}
的配置 的
internal class UserConfiguration : EntityTypeConfiguration<User>
{
internal UserConfiguration()
{
ToTable("Users");
HasKey(x => x.Id);
Property(x => x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Name)
.IsRequired()
.HasMaxLength(128);
Property(x => x.Password)
.IsRequired()
.HasMaxLength(128);
Property(x => x.Email)
.IsRequired()
.HasMaxLength(128);
}
}
internal class PersonConfiguration : EntityTypeConfiguration<Person>
{
internal PersonConfiguration()
{
ToTable("Persons");
Property(x => x.FirstName)
.IsRequired()
.HasMaxLength(16);
Property(x => x.MiddleName)
.IsOptional()
.HasMaxLength(16);
Property(x => x.LastName)
.IsRequired()
.HasMaxLength(16);
}
}
必须在DbSets中始终如一地创建链接(FK)对象,如下所示:
var db = new MainDataContext();
var user = new User
{
Name = "someUser",
Password = "somePassword",
Email = "someEmail"
};
db.Users.Add(user);
db.SaveChanges();
// After some time in other some place
var person = new Person
{
Id = user.Id,
FirstName = "someFirstName",
LastName = "someLastName"
};
db.Persons.Add(person);
db.SaveChanges();
在捕获到最后一次SaveChanges DbEntityValidationError之后:“一个或多个实体的验证失败。有关详细信息,请参阅'EntityValidationErrors'属性。”所需用户的字段有3个验证错误。
如何单独向FK(继承)关联的DbSets添加条目?
更新
我找到了一个解决方案。但为此你必须删除旧用户。我想这样做而不删除,因为如果Users表与其他表关联,那么它将无法删除。
var db = new MainDataContext();
var user = new User
{
Name = "someUser",
Password = "somePassword",
Email = "someEmail"
};
db.Users.Add(user);
db.SaveChanges();
// After some time in other some place
var person = new Person
{
Id = user.Id,
Name = user.Name,
Password = user.Password,
Email = user.Email,
FirstName = "someFirstName",
LastName = "someLastName"
};
db.Users.Remove(user);
db.Persons.Add(person);
db.SaveChanges();
但还有另一个问题 - 为人物对象生成一个新的Guid。
如何在不删除用户的旧记录的情况下解决问题?
答案 0 :(得分:1)
包含用例更新:
你不应该在这里使用继承。您应该使用实体之间的组合和一对一关系:
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public virtual UserInfo Information{get;set;}
}
internal class UserConfiguration : EntityTypeConfiguration<User>
{
internal UserConfiguration()
{
ToTable("Users");
HasKey(x => x.Id);
Property(x => x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Name)
.IsRequired()
.HasMaxLength(128);
Property(x => x.Password)
.IsRequired()
.HasMaxLength(128);
Property(x => x.Email)
.IsRequired()
.HasMaxLength(128);
}
}
public class UserInfo
{
[ForeignKey("InfosUser")]
[Key]
public UserId {get;set;}
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public virtual User InfosUser {get;set;}
}
internal class UserInfoConfiguration : EntityTypeConfiguration<UserInfo>
{
internal UserInfoConfiguration()
{
ToTable("Persons");
Property(x => x.FirstName)
.IsRequired()
.HasMaxLength(16);
Property(x => x.MiddleName)
.IsOptional()
.HasMaxLength(16);
Property(x => x.LastName)
.IsRequired()
.HasMaxLength(16);
HasRequired(ui=>ui.InfosUser).WithOptional(u=>u.Information)
}
}
并使用它:
var db = new MainDataContext();
var user = new User
{
Name = "someUser",
Password = "somePassword",
Email = "someEmail"
};
db.Users.Add(user);
db.SaveChanges();
// After some time in other some place
var user = db.GetPersonFromDb(Id);// Get early saved person from db
var information = new UserInfo
{
FirstName = "someFirstName",
LastName = "someLastName",
}
user.Information = information;
db.SaveChanges();
答案 1 :(得分:0)
问题似乎是创建的对象不是Person对象。如果将User.id值插入Person表,则可以将该用户作为Person查找并对其进行udpate。
Guid id;
using (var db = new MainDataContext())
{
var user = new User
{
Name = "someUser",
Password = "somePassword",
Email = "someEmail"
};
db.Users.Add(user);
db.SaveChanges();
id = user.Id;
}
// After some time in other some place
//pause here and insert the id GUID into the Person table
using (var db = new MainDataContext())
{
var person = db.Persons.Find(id);
person.FirstName = "someFirstName";
person.LastName = "someLastName";
db.SaveChanges();
}
将用户的ID添加到EF之外的Person表中可实现您想要的upcast。您可以通过直接数据库更新将对象从“用户”升级到“人”。