如何映射回来获取除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文件位于名为doc
的XDocument
。 我将解释下面的代码。
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