中央ID表的最佳代码优先方法
本文关键字:方法 代码 最佳 ID 中央 | 更新日期: 2023-09-27 18:18:13
我们使用实体框架代码优先为这个项目的数据库。
我们的需求需要一个中央'Resource'表,其中包含ResourceId (uniqueidentifier NOT NULL DEFAULT (newsequentialid()))的单列。各种表将使用这个表作为它们的ID。
Profile - ProfileId (uniqueidentifier NOT NULL)Organization - OrganizationId (uniqueidentifier NOT NULL)文档=文档id (uniqueidentifier NOT NULL)
因此,如果我创建一个新的概要文件记录,我将创建一个新的资源记录,并使用顺序创建的Guid作为新的概要文件记录的ID。
这样做的原因是为了防止Profile中的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);
然而,我想知道,我们可以定义我们的类/模型从资源继承,并得到更好的结果吗?
你们有人用过这样的数据库结构吗?
实际上,由于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
的主键也是一个外键。
更新:
这是我认为更好的另一个解决方案,这也将在您想要从Resource
实体访问Profile
实体的情况下工作:
我给Resource
实体添加了一个Profile
属性:
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
对象。
相反,我在保存实体时通过覆盖DbContext
上的SaveChanges
方法创建它,如下所示:
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();
}
}