Entity Framework - CTP4 - Code First - 如何关闭自动复数?

Posted

技术标签:

【中文标题】Entity Framework - CTP4 - Code First - 如何关闭自动复数?【英文标题】:Entity Framework - CTP4 - Code First - How to turn off the automatic pluralization? 【发布时间】:2010-08-30 13:16:51 【问题描述】:

我的实体名称是“Contact”,我的表名称是“Contact”。但是,默认的复数支持使 EF4 查找名为“Contacts”的表。有人知道如何关闭多元化支持吗?

This 的帖子有一些关于多元化支持的细节。但还是没有给我答案。

我在this 帖子中看到以下文字。首先,我不知道我需要哪个物理 .tt 文件来进行此更改。另外,我想只为一个应用关闭此功能,而不是全部关闭。

T4 Toolbox 中的代码生成器有 复数默认开启 在 Visual Studio 2010 中。如果需要 无需生成 DAL 多元化,也许是为了 兼容性原因,可以转 通过添加关闭此选项 以下行到 .tt 文件之前 调用 generator.Run() 方法。

C# generator.Pluralize = false;

VB generator.Pluralize = False

更新

以下是我使用的代码,我收到以下错误:-

联系方式

 public class Contact
 
 public int ContactID  get; set; 
 public string FirstName  get; set; 
 public string LastName  get; set; 
 public string Title  get; set; 
 public DateTime AddDate  get; set; 
 public DateTime ModifiedDate  get; set; 
 

上下文:-

 public class AddressBook : DbContext
 
 public DbSet<Contact> Contact  get; set; 

 protected override void OnModelCreating(ModelBuilder modelBuilder)
 
  modelBuilder.Entity<Contact>().MapSingleType().ToTable("dbo.Contact");
 

主程序:-

using (var context = new AddressBook())
  
   var contact = new Contact
   
   ContactID = 10000,
   FirstName = "Brian",
   LastName = "Lara",
   ModifiedDate = DateTime.Now,
   AddDate = DateTime.Now,
   Title = "Mr."

   ;
   context.Contact.Add(contact);
   int result = context.SaveChanges();
   Console.WriteLine("Result :- " + result.ToString());

  

我在“context.Contact.Add(contact);”上收到以下错误:-

System.InvalidOperationException: 支持“地址簿”的模型 自数据库以来上下文已更改 被创建。要么手动 删除/更新数据库,或调用 Database.SetInitializer 与 IDatabaseInitializer 实例。为了 例如, 重新创建DatabaseIfModelChanges 策略将自动删除并 重新创建数据库,并且可以选择 用新数据播种它。在 System.Data.Entity.Infrastructure.CreateDatabaseOnlyIfNotExists1.InitializeDatabase(TContext context) at System.Data.Entity.Infrastructure.Database.Initialize() at System.Data.Entity.Internal.InternalContext.Initialize() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.EfInternalQuery1.Initialize() 在 System.Data.Entity.DbSet1.ActOnSet(Action action,EntityState newState, TEntity entity) at System.Data.Entity.DbSet1.Add(TEntity 实体)在 CodeFirst.Client.Program.Main(字符串 [] args) 在 E:\Ashish\Research\VS Solutions\EntityFramework\CodeFirstApproach_EF_CTP4\CodeFirst.Client\Program.cs:第 35 行

我确定我在某个地方犯了一个愚蠢的错误,只是无法弄清楚。有人可以提供一些方向吗?

回答 在 Pault 的帮助下,我描述了这个问题和解决方案 here。

【问题讨论】:

..作为旁注:在我看来,保持表名复数形式是一种很好的做法。它们代表条目的集合,而不是单个条目。 +1 Arve,我同意。但是,您可以理解我无法更改现有数据库中的表名。 【参考方案1】:

我正在添加第三个答案,因为我对问题的理解发生了变化……对我来说有那么糟糕吗? ;)

就像我在评论中所说的那样,我仍在学习,我还没有尝试使用现有数据库进行此操作。就是说,希望其中之一能有所帮助:

我提到的 Scott Guthrie (http://weblogs.asp.net/scottgu/archive/2010/08/03/using-ef-code-first-with-an-existing-database.aspx) 的帖子中有某位 Jeff 的评论说这会有所帮助(我建议阅读完整评论,因为他解释得更详细):

Database.SetInitializer<AddressBook>(null); //AddressBook being the context

最近,我还偶然看到了 Rowan Miller 在此帖子 (http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4announcement.aspx?PageIndex=2) 下方的评论。他建议这可能是一种选择:

public class ProductContext : DbContext

   protected override void OnModelCreating(ModelBuilder modelBuilder)
   
       modelBuilder.IncludeMetadataInDatabase = false;
   
   ...

希望其中之一能让你走上正轨。

【讨论】:

正轨!!! Database.SetInitializer(null) 是要走的路。我需要将此作为我程序的第一行。谢谢一吨! :-) 我读了那篇文章,但是,我没有看 cmets。经验教训:- 在一篇很棒的博客文章中阅读 cmets 是一件有用的事情。 我想知道 Scot 如何运行他在 weblogs.asp.net/scottgu/archive/2010/07/23/… 上的样本中的样本,他在其中使用现有数据库并映射到不同的表(tblDinners 而不是 Dinners)。 我在这里描述了这个问题和解决方案:- ashishrocks.spaces.live.com/blog/cns!BED6CE34F24CB429!540.entry【参考方案2】:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
        base.OnModelCreating(modelBuilder);
    

【讨论】:

【参考方案3】:

您只是想针对特定的表名吗?

如果是这样,这可能就是您正在寻找的答案:

public class FooDataContext : DbContext

    public DbSet<Contact> Contacts  get; set; 


    protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
    
        modelBuilder.Entity<Contact>().MapSingleType().ToTable("Contact");
    

这有帮助还是我完全没有抓住重点?

【讨论】:

感谢您的宝贵时间。是的,我试图定位一个特定的表名(在这种情况下不是复数)。我正在使用与您建议的非常相似的代码并出现错误。请参阅我更新的问题。【参考方案4】:

开箱即用,代码优先的东西不会修改或删除现有数据库。我猜你有一个现有的数据库,要么是手动创建的,要么是通过之前运行程序创建的框架,然后你更改了 Contact 类。一次修复此错误的快速方法是手动删除您的数据库,或更新它以匹配您的模型。

但是,代码优先功能集的真正强大之处在于允许快速创建和重构域,而不必担心在开发早期创建和维护数据库脚本。为此,我个人发现每次更改模型时允许框架为我删除数据库很有用。当然,这也意味着我想在数据库中植入测试数据。

您可以这样做:

public class MyCustomDataContextInitializer : RecreateDatabaseIfModelChanges<MyCustomDataContext> //In your case AddressBook

    protected override void Seed(MyCustomDataContext context)
    
        var contact = new Contact
        
            ContactID = 10000,
            FirstName = "Brian",
            LastName = "Lara",
            ModifiedDate = DateTime.Now,
            AddDate = DateTime.Now,
            Title = "Mr."
        ;
        context.Contact.Add(contact);
        context.SaveChanges();
    

然后你需要注册这个初始化器(比如在 Application_Start() 中,如果它是一个 Web 应用程序):

Database.SetInitializer(new MyCustomDataContextInitializer());

请注意,您需要:

using System.Data.Entity.Infrastructure;

这有帮助吗?

【讨论】:

Paul,我有一个现有的数据库,我正在围绕它设计一个对象模型。因此,首先我创建了我的 POCO,并考虑使用代码优先并撞到了这堵墙。在这种情况下,代码优先不是要走的路吗?如果是,为什么我会收到此错误?如果不是,在这种情况下最好的方法是什么? 好吧,我自己还在学习这些东西,所以我不完全确定使用现有数据库做这件事的细节。也就是说,Scott Gu 有一篇关于这件事的博文:weblogs.asp.net/scottgu/archive/2010/08/03/…【参考方案5】:
    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    
        modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
    

【讨论】:

以上是关于Entity Framework - CTP4 - Code First - 如何关闭自动复数?的主要内容,如果未能解决你的问题,请参考以下文章

MVC5 Entity Framework学习之Entity Framework高级功能

Entity Framework 学习系列 - 认识理解Entity Framework

Entity Framework Code-First(23):Entity Framework Power Tools

Entity Framework怎么GroupBY多个字段

entity framework 公共类

Entity Framework Fluent API