如何映射回来获取除MVC中的模型之外的实际sql表列名?

我将我的表列名称映射到通用方式,以便在模型中使用它们。 喜欢:

public UserEntityMapper() { ToTable("tbl_User"); HasKey(m => m.UserKey); Property(p => p.InsuredKey).HasColumnName("User_KEY"); Property(p => p.FirstName).HasColumnName("FIRST_NAME"); } 

如果我知道在页面上使用模型修改了FirstName字段,那么需要知道sql表中的列名是’First_Name’

无论如何接近它。

谢谢

阅读映射

我之前看到过类似的问题,而且基于拆分DbSet生成的SQL字符串,有些问题不太令人满意。 无法访问的内部类型阻止了尝试访问映射元数据。 它保持(并且不停地)告诉我这些信息是如此隐藏。 总之,这是你自己的映射。

所以我做了一些鬼混,看看能否在这里改进一些东西。 因为可以从edmx文件中轻松读取所有内容,所以我就是从这里开始的。 终于到了那里。 它是以下代码,edmx文件位于名为docXDocument 。 我将解释下面的代码。

 var xn = XName.Get("Mappings", doc.Root.GetDefaultNamespace().ToString()); var mappingsNode = doc.Descendants(xn).Descendants().First(); var mappingDoc = XDocument.Parse(mappingsNode.ToString()); xn = XName.Get("MappingFragment", mappingDoc.Root .GetDefaultNamespace().ToString()); var mappings = mappingDoc .Descendants(xn) .Select(x => new { Entity = x.Attribute("StoreEntitySet").Value, Mapping = x.Descendants() .Select(d => new { Property = d.Attribute("Name") .Value, Column = d.Attribute("ColumnName") .Value }) }); 

来自非常小的edmx的示例输出:

 Entity Property Column --------------------------------------------- Category CategoryID CategoryID Name CategoryName Description Description Product ProductID ProductID Name ProductName QuantityPerUnit QuantityPerUnit UnitPrice UnitPrice StartDate StartDate 

说明:

edmx文件有一个固定的结构,我在这里总结:

    ...         ...          ...    ...   

Mappings部分就是我们追求的目标。 所以我首先创建这个部分的新XDocument

 var xn = XName.Get("Mappings", doc.Root.GetDefaultNamespace().ToString()); // First descendant of the "Mappings" node, which is the "Mapping" node var mappingsNode = doc.Descendants(xn).Descendants().First(); var mappingDoc = XDocument.Parse(mappingsNode.ToString()); 

“Mapping”节点有自己的命名空间,因此我将其解析为XDocument以获取此命名空间,通过该命名空间可以查询其节点。 因此,我可以得到映射片段:

 xn = XName.Get("MappingFragment", mappingDoc.Root .GetDefaultNamespace().ToString()); var mappings = mappingDoc.Descendants(xn) ... 

也许有更好的方法来访问这些节点,但我不太XDocument这个XDocument API。

然后,这是一个拉出正确属性并将它们投影到可查询结构的问题。

思考

它工作正常,但它根本不优雅。 它在很大程度上取决于edmx结构,所以它可以打破任何时刻。 我认为应该有一个体面,方便的方式来读取上下文的元数据。

顺便说一下,如果你以代码优先工作,你可以通过EdmxWriter生成一个EdmxWriter

在解决另一个问题时,我找到了更好的方法来实现这一目标。 我认为,当我写下第一个答案时,这甚至都不可能。

要从CLR类型名称开始查找商店名称,我们必须访问EDM模型的store-CLR空间。 这就是类和属性之间的映射,另一方面是表和列的映射。 知道这一点只需要仔细剖析深层物体的内容以获得理想的结果:

 public IEnumerable> GetTableAndColumns() { var entityContainerMappings = (this as IObjectContextAdapter).ObjectContext .MetadataWorkspace.GetItems(DataSpace.CSSpace) .OfType(); var entityTypeMappings = entityContainerMappings .SelectMany(m => m.EntitySetMappings .Where(esm => esm.EntitySet.ElementType.Name == typeof(TEntity).Name)) .SelectMany(esm => esm.EntityTypeMappings).ToArray(); var propertyMappings = (from etm in entityTypeMappings from prop in etm.EntityType.Properties join pm in entityTypeMappings.SelectMany(etm => etm.Fragments) .SelectMany(mf => mf.PropertyMappings) .OfType() on prop.Name equals pm.Property.Name select new {etm, prop, pm} ); return propertyMappings.Select(x => Tuple.Create(x.etm.EntitySetMapping.EntitySet.Name, x.pm.Column.Name, x.prop.DeclaringType.Name, x.prop.Name)); } 

这是DbContext子类型中的方法。 对于指定的类型,它返回包含的元组

  • 表名
  • 列名称
  • CLR类名
  • 物业名称

对于istance:

 Item1 Item2 Item3 Item4 =================================================== Products ProductId Product Id Products ProductName Product Name Products QuantityPerUnit Product QuantityPerUnit Products UnitPrice Product UnitPrice Products StartDate Product StartDate Products RowVersion Product RowVersion