中央ID表

时间:2015-10-16 18:27:06

标签: c# entity-framework-6

我们正在为该项目的数据库使用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);

但是,我想知道,我们可以定义我们的类/模型来继承资源并获得更好的结果吗? 你有没有像这样的数据库结构工作?

1 个答案:

答案 0 :(得分:1)

实际上,由于ProfileIdOrganizationId的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();
    }
}