实体框架(4.3)寻找单数名称而不是复数(当实体名称以“s”结尾时)

时间:2012-02-25 06:33:31

标签: c# .net entity-framework entity-framework-4 entity-framework-4.3

这是我的情况: 我一直在研究ASP.NET MVC 3应用程序。它有一个数据库(由db项目构建;我将以db-first为基础),我有一个edmx模型,然后是一组POCO。我的实体在数据库中有多个名称,POCO具有单数名称。一切都很好地映射而没有问题。

或者直到我添加了一个新表(称为TransactionStatuses)。现在所有旧实体仍在工作,但新实体却没有。当我试图将其与相关实体一起急切地加载时:

var transactions = (from t in db.Transactions.Include(s => s.TransactionStatus) //TransactionStatus - navigation property in Transactions to TransactionStatuses
                    where t.CustomerID == CustomerID
                    select t).ToList();

我得到了

  

无效的对象名称'dbo.TransactionStatus'。

我甚至做了一个更简单的测试:

List<TransactionStatus> statuses = db.TransactionStatuses.ToList();

=同样的结果。

我已经从数据库更新(甚至重新创建)了edmx,并且经过它来回尝试找出dbo.TransactionStatus * es *的映射有什么不同把整个事情都绊倒了。

如果有人能指出我的方向,那就太好了。

P.S。关闭多元化不是一种选择,谢谢。

更新:我明白了 - 我的答案如下。

4 个答案:

答案 0 :(得分:32)

这可能正在发生,因为即使意图使用Database First流程,实际上应用程序正在使用Code First进行映射。让我解释一下,因为这可能令人困惑。 : - )

在Visual Studio中使用Database First和Visual Studio中的DbContext模板时,会发生三件非常重要的事情。首先,新的实体数据模型向导会向您的应用添加一个连接字符串,其中包含Database First模型(即EDMX)的详细信息,以便在运行应用程序时可以找到此模型。连接字符串将如下所示:

<connectionStrings>
    <add name="MyEntities"
    connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=MyEntities;integrated security=True;multipleactiveresultsets=True;App=EntityFramework&quot;"
    providerName="System.Data.EntityClient" />
</connectionStrings>

其次,生成的上下文类调用基本DbContext构造函数,指定此连接字符串的名称:

public MyEntities()
: base("name=MyEntities")
{
}

这告诉DbContext在配置中查找并使用“MyEntities”连接字符串。使用“name =”表示如果找不到连接字符串,DbContext将抛出 - 它不会按照惯例继续创建连接。

如果要使用Database First,则必须使用与生成的连接字符串类似的连接字符串。具体来说,它必须包含模型数据(来自EDMX的csdl,msl,ssdl),并且必须确保DbContext找到它。将调用更改为基础构造函数时要非常小心。

第三件事是OnModelCreating在生成的上下文中被覆盖并被抛出:

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

这样做是因为在使用Code First时才会调用OnModelCreating。这是因为OnModelCreating完全是关于创建模型的,但是当您使用Database First时,模型已经存在 - 在运行时没有任何内容可以创建。因此,如果调用OnModelCreating,则可能是因为您开始使用Code First而没有意义,通常是因为连接字符串的更改或对基本构造函数的调用。

现在,您可能希望使用Code First映射到现有数据库。这是一个很棒的模式并且完全支持(请参阅http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx),但您需要确保为此设置适当的映射。如果映射设置不正确,那么您将获得类似此问题中的异常。

答案 1 :(得分:7)

知道了! 可怕的,可怕的经历......

简而言之: EF无法正确复数以“s”结尾的实体名称(例如“状态”,“校园”等)

以下是我如何得到它并证明。

  • 我已经多次创建并重新创建了原始设置,结果相同。
  • 我也尝试将我的表重命名为TransStatus之类的东西 - 没有运气。
  • 在我研究这个问题时,我遇到了pluralization article by Scott Hanselman,他为sheepgoose等字词添加了复数规则。这让我想到“如果问题出现在实体的实际名称中会怎样?
  • 我特意搜索了status这个词,找到了this report of the problem on Connect。我急着尝试重命名我的实体......
  • TransactionStatuses重命名为TransactionStates(即使将列保持为StatusID也解决了问题!我现在可以获得List<TransactionState> statuses = db.TransactionStates.ToList();
  • 我认为问题在于名字中的特定单词status ...但是在声音向朋友抱怨之后我被建议可能问题是以“s”结尾的单词。所以我决定把它检查出来。
  • 我设置了另一个名为Campuses的表,并匹配POCO Campus(并更新了edmx)。简单测试List<Campus> test = db.Campuses.ToList();并得到了现在预期的
  

无效的对象名称'dbo.Campus'。

所以你去了,强大的EF无法处理以“s”结尾的单词的复数。希望下一个遇到问题的可怜的人会发现这个问题并为他或她自己节省3-4个小时的痛苦和挫折感。

答案 2 :(得分:0)

你提到EDMX,但我不知道你是先用EDMX或代码先做数据库,而只是用EDMX来看看发生了什么。

如果您使用的是Code First,则可以使用配置来指定表名。 Data Annotation是[Table(“TransactionStatuses”)],fluent是modelBuilder.Entity()。ToTable(“TransactionStatuses”)。 (我正在从内存中键入注释和流畅的代码,因此请仔细检查引用。;))

如果您首先使用数据库,那么SSDL应该完全知道数据库表的名称,所以我猜测您首先使用的是代码。 edmx只是为了探索。 (???)

HTH

答案 3 :(得分:0)

叹息。类和模型照片和视频的问题类型相同;它正在寻找照片和视频表。我讨厌只更改表名,但看起来没什么选择。