实体框架模型优先:以编程方式创建 UNIQUE 约束

Posted

技术标签:

【中文标题】实体框架模型优先:以编程方式创建 UNIQUE 约束【英文标题】:Entity Framework model first: create UNIQUE constraint programmatically 【发布时间】:2018-04-06 13:11:10 【问题描述】:

我正在尝试向我的“UserAccount”实体/类的“用户名”属性添加一个 UNIQUE 约束。使用代码优先,这没有问题,但对于模型优先,我找不到任何关于如何实现这一点的信息。 设计器不支持此功能。我不能使用注释,因为实体类是自动生成的。我不能使用 Fluent API,因为 OnModelCreating() 方法没有在模型优先中调用,因此我没有 DbModelBuilder 实例。 我唯一能想到的就是在应用程序启动时执行某种手动 SQL 语句来创建 UNIQUE 约束,这违背了 EF 的目的。 这是我当前的 DbContext 类:

 public partial class UserAccountsModelContainer : DbContext
 
    public UserAccountsModelContainer()
        : base("name=UserAccountsModelContainer")
    

    

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        throw new UnintentionalCodeFirstException();
    

    public virtual DbSet<UserAccount> UserAccounts  get; set; 

我什至不会费心发布 UserAccount 类,因为它是自动生成的,不应该修改(我知道 DbContext 也是自动生成的,但可以修改它) . 对此的任何帮助表示赞赏!

【问题讨论】:

让我们面对现实吧……模型优先正在死去,取而代之的是代码优先。如果您真的很幸运,有人会提出或多或少可行的解决方案,但请仔细考虑您是否可以为您的项目摆脱模型优先。 已经开始了 ;) 我简直不敢相信这样一个简单的任务从未集成到模型优先中。 【参考方案1】:

首先,我也建议您切换到 Entity Framework Code First。它使您可以更好地控制使用 EF 可能实现的每件事。

我以前从未使用过它,但我知道Model Conventions。它们适用于模型配置。也许这将是一种为应配置为唯一约束的已定义模型类型/属性设置约定的方法。

基于以下内容,应该可以在创建数据库时首先修改模型的设置。

模型约定基于底层模型元数据。那里 是 CSDL 和 SSDL 的约定。创建一个实现的类 IConceptualModelConvention 来自 CSDL 约定和实现 SSDL 约定的 IStoreModelConvention。

来源:http://www.entityframeworktutorial.net/entityframework6/custom-conventions-codefirst.aspx

有两种类型的模型约定,概念(C-Space)和 商店(S 空间)。这种区别表明管道中的哪个位置 约定被执行。将 C-Space 约定应用于模型 应用程序构建,而应用 S-Space 约定 到模型的版本。

来源:https://entityframework.codeplex.com/wikipage?title=Custom%20Conventions

更多示例实现,包括。解释见msdn。我想它们对您的情况很有帮助。

来自 MSDN 的一个示例:

public class DiscriminatorRenamingConvention : IStoreModelConvention<EdmProperty>  
  
    public void Apply(EdmProperty property, DbModel model)  
                
        if (property.Name == "Discriminator")  
          
            property.Name = "EntityType";  
          
      

它将 Discriminator 列重命名为 EntityType。这是一个非常简单的示例,但您可以对其进行修改以解决您的问题:

public class ModelBasedConvention : IConceptualModelConvention<EdmProperty>

    public void Apply(EdmProperty property, DbModel model)
    
        if (property.Name == "Username"
            && property.DeclaringType.GetType() == typeof(UserAccount))
        
            property.AddAnnotation("UniqueKey", property);
        
    

【讨论】:

感谢您的详细回答。鉴于完成这样一个简单任务的复杂性,我决定改用代码优先(基于 grek40 的回答和我自己的测试)。

以上是关于实体框架模型优先:以编程方式创建 UNIQUE 约束的主要内容,如果未能解决你的问题,请参考以下文章

实体框架代码优先 MaxLength 和 FixedLegth(char 与 varchar)

刷新在实体框架中使用数据库优先方法模型创建的实体中的数据

PHP中的代码优先实体框架模型

将实体框架从数据库优先转换为代码优先

实体框架代码优先的多对多关系的最佳方法

如何在实体框架中定义存储过程(代码优先)?