我正在尝试找出一种方法来获取给定实体类型的基础 SQL 表名称。我已经尝试过 MetadataWorkspace 查询,虽然我可以从对象或存储空间中获取大量信息,但我似乎无法弄清楚如何在两者之间进行映射。
假设我在对象模型中有一个名为 Lookup 的类型 - 如何在数据库中找到表名 (wws_lookups)?
我可以查询 CSpace 和 SSpace 的所有 EntityType 对象,并且可以看到两者都正确列出,但我不知道如何从 CSpace 获取 SSpace。
有什么办法可以做到这一点吗?
I'm trying to figure out a way to get the underlying SQL table name for a given entity type. I've experimented around with the MetadataWorkspace queries and while I can get lots of information from the object or the storage space, I can't seem to figure out how to map between the two.
So say I have a type in the object model called Lookup - how do I find the tablename (wws_lookups) in the database?
I can query all the EntityType objects for CSpace and SSpace and I can see both listed correctly but I can't figure out how to get SSpace from CSpace.
Is there any way to do this?
发布评论
评论(26)
我使用 Nigel 的方法(从
.ToTraceString()
中提取表名),但进行了一些修改,因为如果表不在默认 SQL Server 模式 (dbo. {表名}
)。我已经为
DbContext
和ObjectContext
对象创建了扩展方法:更多详细信息请参见:
实体框架:获取来自实体的映射表名称
I use Nigel's approach (extracting table name from
.ToTraceString()
) but with some modifications, because his code won't work if the table is not in the default SQL Server schema (dbo.{table-name}
).I've created extension methods for
DbContext
andObjectContext
objects:More details here:
Entity Framework: Get mapped table name from an entity
编辑
由于 EF 6.1 中的新功能,此答案现已过时: 表类型之间的映射。 先去那里!
我对其他答案有疑问,因为我有派生类型。我让这个方法(在我的上下文类中)起作用 - 目前我的模型中只有一层继承
注意有计划 改进元数据 API,如果这没有达到我们想要的效果,那么我们可以查看 EF 类型和类型之间的代码优先映射表格
EDIT
This answer now obsolete due to new feature in EF 6.1 : mapping between table types. Go there first!
I had a problem with the other answers because I have a derived type. I got this method (inside my context class) to work - I have only one layer of inheritance in my model at the moment
NB There are plans to improve the Metadata API and if this isn't getting what we want then we can look at EF Code First Mapping Between Types & Tables
这里的大多数答案不适用于派生类。这个可以。并为您提供了架构。我在此处合并了答案并进行了改进稍微修改一下(通过取出诸如 First() 和 Single() 之类的内容,并将它们转换为诸如Where() 和 SelectMany() 之类的内容并返回模式名称)。
这适用于 EF 6.1+
Most of the answers here don't work with derived classes. This one does. And gives you the schema too. I combined the answers here and improved on it a little (by taking out things like First() and Single() and converting them to things like Where() and SelectMany() and returning the schema name).
This works with EF 6.1+
当您使用注释显式告诉 EF 要使用哪个表名时,为特殊情况添加另一个答案。例如,如果您:
您可以轻松访问
TableAttribute
注释来查找表名称:给定示例的表名称为
tblCompany
。作为现成的方法:(
我知道这对OP没有帮助,但考虑到问题的标题,人们可能会在这里寻找这个答案。)
Adding another answer for the special case when you use annotations to explicitly tell EF which table name to use. For example, if you have:
You can easily access the
TableAttribute
annotation to find the table name:which is
tblCompany
for the given sample.As ready-to-use method:
(I am aware that this will not help the OP but given the title of the question, people may end up here who may be looking for this answer.)
在 entity-framework-core 版本 3.0 和 3.1 相当 琐碎:
In entity-framework-core versions 3.0 and 3.1 it's rather trivial:
不,不幸的是,不可能使用元数据 API 来获取给定实体的表名。
这是因为映射元数据不是公开的,因此无法使用 EF 的 API 从 C-Space 转到 S-Space。
如果您确实需要这样做,您始终可以通过解析 MSL 自己构建地图。这不适合胆小的人,但应该是可能的,除非您使用 QueryViews (这是非常罕见的),此时它对于所有意图和目的都是不可能的(您必须解析 ESQL...啊!)
Alex James
Microsoft。
No, unfortunately it is impossible using the Metadata APIs to get to the tablename for a given entity.
This is because the Mapping metadata is not public, so there is no way to go from C-Space to S-Space using the EF's APIs.
If you really need to do this you could always build the map yourself by parsing the MSL. This is not for the faint of heart, but it should be possible, unless you are using QueryViews (which are incredibly rare), at which point it is for all intents and purposes impossible (you would have to parse ESQL... argh!)
Alex James
Microsoft.
如果您在 EF6 中执行 codefirst,则只需将类似以下内容添加到 dbcontext 类中即可。
If you're doing codefirst in EF6, you can just add something like the following to your dbcontext class.
有一种方法可以使用 EF 删除数据,而无需先加载它,我在以下内容中详细描述了它: http://nigelfindlater.blogspot.com/2010/04/how-to-delete-objects-in-ef4-without.html
技巧是将 IQueriable 转换为 ObjectQuery 并使用 ToTraceString 方法。然后编辑生成的 sql 字符串。它可以工作,但您需要小心,因为您正在绕过 EF 为维护依赖性和约束而建立的机制。但出于性能原因,我认为这样做是可以的......
玩得开心......
奈杰尔......
There is a way to delete data using EF without having to load it first I described it in a little more detain in: http://nigelfindlater.blogspot.com/2010/04/how-to-delete-objects-in-ef4-without.html
The trick is to cast the IQueriable into an ObjectQuery and use the ToTraceString method. Then edit the resulting sql string. It works but you need to be careful because you are bypassing the the mechanisms that EF has in place for maintaining dependancies and contraints. But for performance reasons I think it's ok to do this....
have fun...
Nigel...
如果您将 T4 模板用于 POCO 类,您可以通过更改 T4 模板来获取它。参见片段:
If you are using the T4 template for POCO classes you can get it by altering the T4 Template. See snippet:
将 EF Core 与 SQL Server 结合使用非常简单:
Using EF Core with SQL server it's as easy as:
一个可能的解决方法(不是很好,但也不是替代方案...):
...然后解析 SQL,这应该非常简单。
A possible workaround (not great, but neither are the alternatives...):
...then parse the SQL, which should be quite simple.
以下是我使用 LINQ to XML 得出的结论。该代码还获取列名称的映射。
Here's what I was able to come up with using LINQ to XML. The code gets the mappings for column names as well.
更好的方法是使用元数据中的 StoreItemCollection。这家伙已经提供了使用它的示例:获取表和关系
A better way is to use the StoreItemCollection from the Metadata. This guy has already provided an example of using it: Get Tables and Relationships
EF 6.1,代码优先:
EF 6.1, code-first:
这是查找表名的另一种方法。这有点奇怪但有效。
VB:
Here is another way to find the table name. It is a bit odd but works.
VB:
您可以尝试 MappingAPI 扩展: https://efmappingapi.codeplex.com/
它真的很容易使用
You can try MappingAPI extension: https://efmappingapi.codeplex.com/
It is really easy to use
这是一个假设您有上下文并且内存中有一个选定实体的版本,您需要找到其真实的表名称。
Here is a version assuming you have context and have a selected entity in memory that you need to find the real table name for.
使用 EF5 和一点点反射,类似下面的内容应该可以解决问题:
调用如下:
Using EF5 and a litle bit o reflection, something like the following should do the trick:
Call it is like this:
实际上我也遇到过同样的问题,并且我生成了一个抽象代码片段,它为您提供了两个
Dictionary>
($table_name,$columns_name_list)。第一个具有数据库表 + 列名称列表,第二个具有本地 EF 实体 + 属性
当然,您可以添加更多针对数据类型的检查,顺便说一句,这将迫使您编写极其复杂的代码。
损益表
抱歉,压缩风格,我是 lambda 狂热者
Actually I've been through the same problem, and I've produced an abstract code snippet which gives you two
Dictionary<string,List<string>>
($table_name,$columns_name_list).First one has database Table + column name list, second one has local EF Entities + properties
Of course you can add more checks against data type, btw imho that would force you to write insanely complicated code.
P&L
P.S. Sorry for the compressed style, I'm a lambda fanatic
在使用 Entity Framework Core 2.0+ 的情况下,您可以使用提供的 API 轻松获取关系元数据。
您需要安装 Microsoft.EntityFrameworkCore.Relational Nuget 包才能使用 Relational() 方法。
In the case of using Entity Framework Core 2.0+, you can easily get the relational metadata using provided APIs.
You need to have Microsoft.EntityFrameworkCore.Relational Nuget package installed to be able to use Relational() method.
如果您只是想要一种快速而肮脏的方法来获取表名称(并且您的应用程序代码中不需要它),您可以查看为 Model.edmx 生成的 XML。在 edmx:Mappings 部分中找到您的实体,并且行:MappingFragment StoreEntitySet="YourTableName" 将为您提供表的实际名称。
If you want just a quick and dirty way to get the table name (and you don't need it in your application's code), you can look at the XML generated for your Model.edmx. Find your entity in the edmx:Mappings section and the line: MappingFragment StoreEntitySet="YourTableName" will give you the table's actual name.
Alex 是对的 - 这是元数据 API 中一个令人遗憾的限制。我必须将 MSL 作为 XML 文档加载,并在处理 C 空间模型时查找 S 空间实体。
Alex is right - this is a sad limitation in the Metadata API. I have to just load the MSL as an XML document and do lookups of S-space entities as I process my C-space model.
在这里复制我对另一个问题的回答。
如果有人还在寻找,这就是我的做法。这是 DBContext 的扩展方法,它采用类型并返回物理列名称及其属性。
这利用对象上下文来获取物理列列表,然后使用“PreferredName”元数据属性将每个列映射到其属性。
由于它使用对象上下文,它会启动数据库连接,因此第一次运行会很慢,具体取决于上下文的复杂性。
要使用它,只需创建一个辅助静态类,并添加上面的函数即可;那么就像调用一样简单
Copying my answer to another question here.
If anyone is still looking, Here's how I did it. This is an extension method for the DBContext that takes a type and returns physical column names and their properties.
This utilizes object context to get physical columns list, then uses the "PreferredName" metadata property to map each column it its property.
Since it uses object context, it initiates a database connection, so the first run will be slow depending on the complexity of the context.
To use it, just create a helper static class, and add above function; then it's as simple as calling
对于 EF6,混合/压缩来自其他答案的代码(VB,我很抱歉):
它适用于 db-first。
遵循 .edmx 文件相对容易理解。
For EF6, mixing/compressing code from other answers here and around (VB, I'm sorry):
It works for db-first.
Relatively easy to understand following an .edmx file.
您可以使用扩展方法从实体类中获取表名称
在这种情况下,您不需要 DbContext 来获取表名,它会在扩展方法中获取它,
这就是我们到达 DbContext 的地方:
用法:
You can use extension method to get Table name from your entity class
In this case, You wont need
DbContext
to get table name , it gets it inside extension methodThis is where we reach to
DbContext
:Usage:
如果您将模型类与
[Table("table_name")]
注释一起使用,则可以使用它。如果类型没有[Table]
注释,它会返回类的名称,因为默认情况下就是类的名称。If you use Model classes with
[Table("table_name")]
annotation, you can use this. If a type has no[Table]
annotation it returns the name of a class, since it is it by default.