我使用流畅的api来更改我的实体的表名称,如:
public class TestMap : EntityTypeConfiguration<Domain.Test>
{
public TestMap()
{
ToTable("Test");
}
}
现在稍后在我的DbContext
中,我想查找某个类型的表名,但当我查看MetadataWorkspace
时,我发现我无法找到类型Domain.Test
。我能找到表格&#34; Tests&#34;但除非我硬编码,否则我无法匹配。所以我的问题是如何在MetadataWorkspace
内找到类型名称。
我用来尝试查找类型Domain.Test
的代码:
ObjectContext octx = (context as IObjectContextAdapter).ObjectContext; ;
var es = octx.MetadataWorkspace
.GetItems<EntityContainer>(DataSpace.SSpace)
.SelectMany(c => c.BaseEntitySets);
我的代码编辑,简单的示例供人们测试:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var db = new Database();
db.Set<Test>().Add(new Test {Name = "test"});
var amount = db.SaveChanges();
}
public abstract class AbstractTest
{
public int Id { get; set; }
}
public class Test : AbstractTest
{
public string Name { get; set; }
}
public class Database : DbContext
{
public Database() : base("Database")
{
this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Remove pluralized tables
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>();
// Add all configurations within the current assembly.
modelBuilder.Configurations.AddFromAssembly(typeof(Database).Assembly);
}
public override int SaveChanges()
{
foreach (DbEntityEntry ent in ChangeTracker.Entries())
{
Type entityType = ent.Entity.GetType();
var names = Utility.GetTableNames(entityType, this);
}
return base.SaveChanges();
}
}
public class AbstractTestMap : EntityTypeConfiguration<AbstractTest>
{
public AbstractTestMap()
{
this.HasKey(t => t.Id);
}
}
public class TestMap : EntityTypeConfiguration<Test>
{
public TestMap()
{
this.Property(t => t.Name)
.HasMaxLength(200);
ToTable("Tests");
}
}
public static class Utility
{
public static IEnumerable<string> GetTableNames<TEntity>(DbContext context)
{
return GetTableNames(typeof(TEntity), context);
}
public static IEnumerable<string> GetTableNames(Type type, DbContext context)
{
var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;
// Get the part of the model that contains info about the actual CLR types
var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
// Get the entity type from the model that maps to the CLR type
var entityType = metadata
.GetItems<EntityType>(DataSpace.OSpace)
.Single(e => objectItemCollection.GetClrType(e) == type);
// Get the entity set that uses this entity type
var entitySet = metadata
.GetItems<EntityContainer>(DataSpace.CSpace)
.Single()
.EntitySets
.Single(s => s.ElementType.Name == entityType.Name);
// Find the mapping between conceptual and storage model for this entity set
var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single()
.EntitySetMappings
.Single(s => s.EntitySet == entitySet);
// Find the storage entity sets (tables) that the entity is mapped
var tables = mapping
.EntityTypeMappings.Single()
.Fragments;
// Return the table name from the storage entity set
return tables.Select(f => (string)f.StoreEntitySet.MetadataProperties["Table"].Value ?? f.StoreEntitySet.Name);
}
}
}
}
答案 0 :(得分:1)
使用此实体:
namespace YourNamespace.Domain{
public class Test{
public int Id { get; set; }
public string Name { get; set; }
}
}
和这张地图:
namespace YourNamespace {
public class TestMap : EntityTypeConfiguration<Domain.Test> {
public TestMap() {
ToTable("Test");
}
}
}
和这个背景:
namespace YourNamespace {
public class MyContext : DbContext{
public DbSet<Test> Tests { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder){
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations
.AddFromAssembly(Assembly.GetExecutingAssembly());
}
}
}
您可以使用此方法:
public static class Utility {
public static IEnumerable<string> GetTableNames<TEntity>(this DbContext context) {
return GetTableNames(typeof(TEntity), context);
}
public static IEnumerable<string> GetTableNames(Type type, DbContext context) {
var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;
// Get the part of the model that contains info about the actual CLR types
var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
// Get the entity type from the model that maps to the CLR type
var entityType = metadata
.GetItems<EntityType>(DataSpace.OSpace)
.Single(e => objectItemCollection.GetClrType(e) == type);
// Get the entity set that uses this entity type
var entitySet = metadata
.GetItems<EntityContainer>(DataSpace.CSpace)
.Single()
.EntitySets
.Single(s => s.ElementType.Name == entityType.Name);
// Find the mapping between conceptual and storage model for this entity set
var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single()
.EntitySetMappings
.Single(s => s.EntitySet == entitySet);
// Find the storage entity sets (tables) that the entity is mapped
var tables = mapping
.EntityTypeMappings.Single()
.Fragments;
// Return the table name from the storage entity set
return tables.Select(f => (string)f.StoreEntitySet.MetadataProperties["Table"].Value ?? f.StoreEntitySet.Name);
}
}
它将返回所有表名的列表。对于单个表实体 - 您的情况 - ,只需使用tableNames.FirstOrDefault(t=> !string.IsNullOrWhiteSpace(t))
。此外,您可以将其用作实用方法或扩展方法:
class Program {
static void Main(string[] args) {
// getting the list:
using (var ctx = new MyContext()){
var tableNames = ctx.GetTableNames<Test>();
foreach (var tableName in tableNames)
Console.WriteLine(tableName);
Console.ReadLine();
}
// getting the single table-name - your case -
using (var ctx = new MyContext()){
var tableNames = ctx.GetTableNames<Test>();
var tableName = tableNames.FirstOrDefault(t=> !string.IsNullOrWhiteSpace(t))
Console.WriteLine(tableName);
Console.ReadLine();
}
}
}
请参阅源文章here。
<强>更新强>
根据更新的问题:我们在这里有一个HierarchyMapping
;所以我们需要更改我们的GetTableNames
方法来支持继承:
public static class Utility {
public static IEnumerable<string> GetTableNames<TEntity>(this DbContext context) {
return GetTableNames(typeof(TEntity), context);
}
public static IEnumerable<string> GetTableNames(Type type, DbContext context) {
var metadata = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace;
// Get the part of the model that contains info about the actual CLR types
var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
// Get the entity type from the model that maps to the CLR type
var entityType = metadata
.GetItems<EntityType>(DataSpace.OSpace)
.Single(e => objectItemCollection.GetClrType(e) == type);
// Get the entity set that uses this entity type
var entitySetTop = metadata
.GetItems<EntityContainer>(DataSpace.CSpace).SelectMany(s => s.EntitySets);
//.Single()
//.BaseEntitySets;
var entitySet = entitySetTop
.SingleOrDefault(s => s.ElementType.Name == entityType.Name);
EntitySet entitySet2 = null;
foreach (var s in entitySetTop) {
if (s.ElementType.Name == entityType.Name) {
entitySet2 = s;
break;
}
var temp = entityType.BaseType;
while (temp != null) {
if (s.ElementType.Name == temp.Name) {
entitySet2 = s;
break;
}
temp = temp.BaseType;
}
if (entitySet2 != null)
break;
}
entitySet = entitySet2;
// Find the mapping between conceptual and storage model for this entity set
var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single()
.EntitySetMappings
.Single(s => s.EntitySet == entitySet);
// Find the storage entity sets (tables) that the entity is mapped
var tables = mapping
.EntityTypeMappings.Where(f => {
if (f.IsHierarchyMapping) {
return f.EntityTypes.Any(e => e.Name == entityType.Name);
}
return f.EntityType.Name == entityType.Name;
}).SelectMany(t => t.Fragments); //.Single()
//.Fragments;
// Return the table name from the storage entity set
return tables.Select(f => (string)f.StoreEntitySet.MetadataProperties["Table"].Value ?? f.StoreEntitySet.Name);
}
}