我们正在为该项目的数据库使用Entity Framework Code First。
我们的要求需要一个中央“资源”表,其中包含一列ResourceId(uniqueidentifier NOT NULL DEFAULT(newsequentialid()))。 各种表将使用此表作为其ID。
配置文件 - ProfileId(uniqueidentifier NOT NULL) 组织 - OrganizationId(uniqueidentifier NOT NULL) Document = DocumentId(uniqueidentifier NOT NULL)
因此,如果我创建一个新的Profile记录,我将创建一个新的Resource记录,并使用该顺序创建的Guid作为新Profile记录的ID。
这样做的原因是为了防止配置文件中的Id作为组织ID存在。 (我知道这很可能是不可能的,但并非不可能。)
现在我们用这样的关系来定义它:
public class Resource : BaseEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ResourceId { get; set; }
public virtual Profile Profile_ProfileId { get; set; }
//...
}
public class Profile : BaseEntity, IAuditableEntity
{
[Key]
public Guid ProfileId { get; set; }
public virtual Resource Resource { get; set; }
//...
}
public class ProfileMapping : EntityTypeConfiguration<Profile>
{
public ProfileMapping()
{
//Primary key
HasKey(t => t.ProfileId);
//Constraints
Property(t => t.ProfileId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
//...
ToTable("Profile");
//Create Relation
HasRequired(t => t.Resource).WithOptional(t => t.Profile_ProfileId);
}
}
然后,当我们创建一个新的Profile时,我们这样做(db是我们DBContext的一个实例):
var res = new Resource();
db.Resource.Add(res);
var newProfile = new Profile{
ProfileId = res.ResourceId,
IsActive = true
};
db.Profile.Add(newProfile);
但是,我想知道,我们可以定义我们的类/模型来继承资源并获得更好的结果吗? 你有没有像这样的数据库结构工作?
答案 0 :(得分:1)
实际上,由于ProfileId
和OrganizationId
的GUID是在同一个数据库服务器上生成的,因此您可以100%保证它们是唯一的。我假设您将让数据库服务器生成GUID。
如果在不同的计算机上生成GUID,则可能有机会(非常小的机会)发生冲突。
无论如何,这是你问题的直接答案:
您可以这样做:
public class Resource
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ResourceId { get; set; }
}
public class Profile
{
[Key]
[ForeignKey("Resource")]
public Guid ProfileId { get; set; }
public Resource Resource { get; set; }
public string Name { get; set; }
public Profile()
{
Resource = new Resource();
}
}
注意Profile
实体如何在其构造函数中创建Resource
实体。另请注意,Profile
的主键也是外键。
<强>更新强>
以下是我认为更好的另一种解决方案,如果您想要从Profile
实体访问Resource
实体,这也会有效:
我向Profile
实体添加了Resource
属性:
public class Resource
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ResourceId { get; set; }
public virtual Profile Profile { get; set; }
}
以下是个人资料实体:
public class Profile
{
[Key, ForeignKey("Resource"), DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid ProfileId { get; set; }
public Resource Resource { get; set; }
public string Name { get; set; }
}
请注意,我不再在构造函数中创建Resource
对象。
相反,我通过覆盖SaveChanges
上的DbContext
方法保存实体时创建它,如下所示:
public class MyContext : DbContext
{
public DbSet<Resource> Resources { get; set; }
public DbSet<Profile> Profiles { get; set; }
public override int SaveChanges()
{
foreach (var profile in ChangeTracker.Entries<Profile>()
.Where(x => x.State == EntityState.Added))
{
profile.Entity.Resource = new Resource();
}
//Here you also need to do the same thing for other Entities that need a row in the Resources table (e.g. Organizations)
return base.SaveChanges();
}
}