简体   繁体   English

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

[英]Entity Framework (4.3) looking for singular name instead of plural (when entity name ends with “s”)

Here's my situation: I have been working on an ASP.NET MVC 3 application for a while. 这是我的情况:我一直在研究ASP.NET MVC 3应用程序一段时间。 It has a database (built out of a db project; I'm going db-first) for which I have an edmx model and then a set of POCOs. 它有一个数据库(是从db项目中建立的;我要以db-first优先),为此我有一个edmx模型,然后有一组POCO。 My entities have plural names in the database and POCOs have singular names. 我的实体在数据库中具有复数名称,而POCO具有单数名称。 Everything maps nicely without a problem. 一切都映射良好,没有问题。

Or used to until I added a new table (called TransactionStatuses). 或习惯直到我添加了一个新表(称为TransactionStatuses)。 Now all of the old entities still work but the new one does not. 现在,所有旧实体仍然可以使用,而新实体则不能。 When I try to eagerly load it together with a related entity: 当我尝试将其与相关实体一起加载时:

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();

I get 我懂了

Invalid object name 'dbo.TransactionStatus'. 无效的对象名称“ dbo.TransactionStatus”。

I even did a simpler test: 我什至做了一个更简单的测试:

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

= same result. =相同的结果。

I have updated (and even re-created) edmx from the db and have gone through it back and forth trying to figure out what is different about the mapping for dbo.TransactionStatus* es * which trips the whole thing up. 我已经从db更新(甚至重新创建)了edmx,并来回遍历了一下,以找出dbo.TransactionStatus * es *映射的不同之处,从而使整个过程崩溃。

If somebody can point me in the direction of a fix it'd be wonderful. 如果有人可以指出修复的方向,那就太好了。

PS Turning off pluralisation is not an option, thanks. PS:谢谢您不要关闭复数。

Update : I figured it out - my answer below. 更新 :我想通了-我的回答如下。

This is probably happening because even though the intention was to use the Database First flow, in actual fact the application is using Code First to do the mapping. 之所以会发生这种情况,是因为尽管意图是使用数据库优先流,但实际上,应用程序正在使用代码优先进行映射。 Let me explain a bit more because this can be confusing. 让我多解释一下,因为这可能会造成混淆。 :-) :-)

When using Database First with the EF Designer and the DbContext templates in Visual Studio three very important things happen. 在Visual Studio中将EF First和dbdesigner模板与Database First一起使用时,会发生三件事。 First, the new Entity Data Model wizard adds a connection string to your app containing details of the Database First model (ie the EDMX) so that when the application is run it can find this model. 首先,新的实体数据模型向导将包含数据库优先模型(即EDMX)详细信息的连接字符串添加到您的应用程序,以便在应用程序运行时可以找到该模型。 The connection string will look something like this: 连接字符串如下所示:

<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>

Second, the generated context class makes a call to the base DbContext constructor specifying the name of this connection string: 其次,生成的上下文类将调用基本DbContext构造函数,并指定此连接字符串的名称:

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

This tells DbContext to find and use the "MyEntities" connection string in the config. 这告诉DbContext在配置中查找和使用“ MyEntities”连接字符串。 Using "name=" means that DbContext will throw if it doesn't find the connection string--it won't just go ahead and create a connection by convention. 使用“ name =”表示DbContext如果找不到连接字符串将抛出该异常-它不会继续按照约定创建连接。

If you want to use Database First, then you must use a connection string like the one that is generated. 如果要使用“数据库优先”,则必须使用连接字符串,例如生成的连接字符串。 Specifically, it must contain the model data (the csdl, msl, ssdl from the EDMX) and you must make sure that DbContext finds it. 具体来说,它必须包含模型数据(来自EDMX的csdl,msl,ssdl),并且必须确保DbContext找到它。 Be very careful when changing the call to the base constructor. 在更改对基本构造函数的调用时要非常小心。

The third thing that happens is that OnModelCreating is overridden in the generated context and made to throw: 发生的第三件事是OnModelCreating在生成的上下文中被覆盖并抛出:

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

This is done because OnModelCreating is only ever called when using Code First. 这样做是因为仅在使用“代码优先”时才调用OnModelCreating。 This is because OnModelCreating is all about creating the model, but when you are using Database First the model already exists--there is nothing to create at runtime. 这是因为OnModelCreating完全是关于创建模型的,但是当您使用Database First时,该模型已经存在-在运行时无需创建任何内容。 So if OnModelCreating is called then it is probably because you started using Code First without meaning to, usually because of a change to the connection string or the call to the base constructor. 因此,如果调用了OnModelCreating,则可能是因为您开始使用Code First而没有意义,通常是因为更改了连接字符串或调用了基本构造函数。

Now, it might be that you want to use Code First to map to an existing database. 现在,可能是您想使用Code First映射到现有数据库。 This is a great pattern and fully supported (see http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx ) but you will need to make sure mappings are setup appropriately for this to work. 这是一个很好的模式,并且得到了完全支持(请参阅http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx ),但是您将需要确保正确设置了映射才能起作用。 If the mappings are not setup correctly then you will get exceptions like the one in this question. 如果映射设置不正确,那么您将获得类似该问题中的异常的信息。

Got it! 得到它了! Horrible, horrible experience... 可怕的,可怕的经历...

In short: EF cannot correctly pluralize entity names that end with "s" (eg "status", "campus", etc.) 简而言之: EF无法正确地将以“ s”结尾的实体名称 (例如“ status”,“ campus”等) 复数

Here's how I got it and proof. 这是我得到它和证明的方法。

  • I've created and re-created my original set up several times with the same result. 我已经创建并重新创建了原始设置几次,但结果相同。
  • I also tried renaming my table to things like TransStatus and the like - no luck. 我还尝试将表重命名为TransStatus之类的东西-祝您好运。
  • While I was researching about this I came across the pluralization article by Scott Hanselman where he added pluralization rules for words like sheep and goose . 在研究此问题时,我遇到了Scott Hanselman复数文章 ,他在其中添加了sheepgoose等单词的复数规则。 This got me thinking " what if he problem is in the actual name of the entity? " 这让我开始思考“ 如果他的问题是实体的实际名称怎么办?
  • I did some searching about the word status in particular and found this report of the problem on Connect . 我特别搜索了单词status ,并在Connect上找到了该问题的报告 I rushed to try renaming my entity... 我赶紧尝试重命名我的实体...
  • Renaming TransactionStatuses to TransactionStates (while even keeping the columns as StatusID ) fixed the issue ! TransactionStatuses重命名为TransactionStates (甚至将列保留为StatusID解决了该问题 I can now get List<TransactionState> statuses = db.TransactionStates.ToList(); 我现在可以获取List<TransactionState> statuses = db.TransactionStates.ToList();
  • I thought the problem was with the particular word status in the name... But after vocally complaining about this to a friend I was suggested that maybe the problem is with the word ending with "s"... So I decided to check it out. 我以为问题在于名称中的特定单词status ...但是在向朋友大声抱怨之后,有人建议我认为问题可能出在以“ s”结尾的单词...所以我决定检查一下出来。
  • I set up another table called Campuses and matching POCO Campus (and updated the edmx). 我成立了一个名为另一台Campuses和匹配POCO Campus (和更新EDMX)。 Did the simple test List<Campus> test = db.Campuses.ToList(); 是否简单测试了List<Campus> test = db.Campuses.ToList(); and got the now expected 得到了现在的期望

Invalid object name 'dbo.Campus'. 无效的对象名称“ dbo.Campus”。

So there you go, the mighty EF cannot handle pluralization of words ending with "s". 这样一来,强大的EF无法处理以“ s”结尾的单词的复数形式。 Hopefully, the next poor bugger hitting the problem will find this question and save him- or herself 3-4 hours of pain and frustration. 希望下一个遇到这个问题的可怜虫可以找到这个问题,并为他或她自己节省3-4个小时的痛苦和沮丧。

Sigh. 叹。 Same type of an issue with the class and model Photo and Video; 类和模型“照片和视频”的问题类型相同; it is looking for the table Photoes and Videoes. 它正在查找表Photoes和Videoes。 I hate to just change the table name, but not much of a choice it looks like. 我讨厌只更改表名,但是看起来没有太多选择。

You mention EDMX but I can't tell if you are doing databse first with EDMX or code first and just using EDMX to see what's going on. 您提到了EDMX,但我无法确定您是先使用EDMX还是先进行代码处理,还是仅使用EDMX来查看发生了什么。

If you are using Code First, then you can use a configuration to specify the table name. 如果使用的是Code First,则可以使用配置指定表名。 Data Annotation is [Table("TransactionStatuses")], fluent is modelBuilder.Entity().ToTable("TransactionStatuses"). 数据注释是[Table(“ TransactionStatuses”)],流利的是modelBuilder.Entity()。ToTable(“ TransactionStatuses”)。 (I'm typing the annotation and fluent code from memory so double check references. ;) ) (我正在从内存中键入注释和流利的代码,因此请仔细检查引用。))

If you are using database first, the SSDL should absolutely be aware of the name of the database table, so I'm guessing that you are using code first & the edmx is just for exploration. 如果您首先使用数据库,则SSDL应该绝对知道数据库表的名称,因此我猜测您首先使用代码,而edmx仅用于探索。 (???) (???)

hth hth

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实体框架会创建一个复数表名,但是视图需要一个单数表名吗? - Entity Framework creates a plural table name, but the view expects a singular table name? 实体框架代码第一个表命名问题,复数形式的单数冲突 - Entity Framework Code First table naming issue, singular confilcts with Plural 实体使用多个覆盖“我的表名称”属性 - Entity is Overriding My Table Name Attribute with a Plural 实体框架 - 按名称获取实体 - Entity framework - get entity by name 实体框架PK名称 - Entity Framework PK Name 添加实体时带有表名的实体框架错误 - Entity Framework bug with table name when add entity 我可以更改实体框架 4.3 代码优先中的默认架构名称吗? - Can I change the default schema name in entity framework 4.3 code-first? 告诉实体框架在生成实体时使用名称“ Children”而不是“ InverseParent” - Tell Entity Framework to use the name “Children” instead of “InverseParent” when generating entities 如何在实体框架中显示注册用户的姓名而不是电子邮件 - How to show the name of the registered user in Entity Framework instead of email Entity Framework Core 获取实体列名 - Entity Framework Core get entity column name
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM