2015-10-16 53 views
0

我们对此项目的数据库使用实体框架代码优先。最佳代码中心ID表第一种方法

我们的需求需要一个中心的'资源'表,带有一列ResourceId(uniqueidentifier NOT NULL DEFAULT(newsequentialid()))。 各种表格将使用此表作为其ID。

简介 - 简档(唯一标识符NOT NULL) 组织 - OrganizationId(唯一标识符NOT NULL) 文件= DocumentId(唯一标识符NOT NULL)

所以,如果我创建一个新的档案记录,我将创建一个新的资源记录并使用该顺序创建的Guid作为新配置文件记录的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); 
    } 
} 

然后,当我们创建一个新的配置文件,我们这样做(DB是我们的DbContext的实例):

var res = new Resource(); 
db.Resource.Add(res); 

var newProfile = new Profile{ 
    ProfileId = res.ResourceId, 
    IsActive = true 
}; 

db.Profile.Add(newProfile); 

不过,我想,我们可以定义我们的类/型号可供资源继承和获得更好的效果?
有没有人用过这样的数据库结构?

+0

如果这只是为了防止重复的主键值这是一个**绝对没用**矫枉过正。 GUID是[非常](http://stackoverflow.com/q/184869/861716)[不太可能](http://stackoverflow.com/q/3138395/861716)被复制。这将是一个没有任何*好处的持续负担。 –

+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的主键也是一个外键。

UPDATE:

这里是另一种解决办法,我认为是更好的,这也将工作的情况下,你想从Resource实体访问Profile实体:

我加了一个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对象。

相反,我创造它时的实体是通过覆盖在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(); 
    } 
} 
+0

那么,那么,我不需要在我的其他代码中处理创建资源?我知道必须有一种方法 –

+0

是的,因为每个'Profile'实例都会创建一个'Resource'对象 –

+0

一个后续问题如果我们想要从资源导航到代码中的配置文件,例如:thisResource.Profile.Name;在这种情况下实现这个目的的最佳方式是什么? –

相关问题