我正在使用EDMX文件中的T4模板生成POCO(假设它们是 MyEntityObject 的子类)。
我有3个实体,例如:
这些实体具有以下关系:
MyTable1.MyTable1ID< => MyTable2.MyTable1ID(MyTable1ID是 MyTable1的外键)
MyTable2.MyTable2ID< => MyTable3.MyTable2ID(MyTable2ID是 MyTable2的外键)
或者在另一种观点中:
MyTable1< = MyTable2< = MyTable3
我想提取所有外键关系
NavigationProperty[] foreignKeys = entity.NavigationProperties.Where(np => np.DeclaringType == entity && ((AssociationType)np.RelationshipType).IsForeignKey).ToArray();
forewach (NavigationProperty foreignKey in foreignKeys)
{
// generate code....
}
我的问题:如何提取两个实体之间链接的列名?
这样的事情:
void GetLinkedColumns(MyEntityObject table1, MyEntityObject table2, out string fkColumnTable1, out string fkColumnTable2)
{
// do the job
}
在示例中
string myTable1Column;
string myTable2Column;
GetLinkedColumns(myTable1, myTable2, out myTable1Column, out myTable2Column);
结果应该是
myTable1Column = "MyTable1ID";
myTable2Column = "MyTable2ID";
答案 0 :(得分:6)
如果您的外键列在概念模型中公开为属性,则第一个答案有效。此外,GetSourceSchemaTypes()方法仅在EF附带的一些文本模板中可用,因此了解此方法的作用会很有帮助。
如果您想要始终知道列名,则需要从存储模型加载AssociationType,如下所示:
// Obtain a reference to the navigation property you are interested in
var navProp = GetNavigationProperty();
// Load the metadata workspace
MetadataWorkspace metadataWorkspace = null;
bool allMetadataLoaded =loader.TryLoadAllMetadata(inputFile, out metadataWorkspace);
// Get the association type from the storage model
var association = metadataWorkspace
.GetItems<AssociationType>(DataSpace.SSpace)
.Single(a => a.Name == navProp.RelationshipType.Name)
// Then look at the referential constraints
var toColumns = String.Join(",",
association.ReferentialConstraints.SelectMany(rc => rc.ToProperties));
var fromColumns = String.Join(",",
association.ReferentialConstraints.SelectMany(rc => rc.FromProperties));
在这种情况下,loader是EF.Utility.CS.ttinclude中定义的MetadataLoader,inputFile是指定.edmx文件名称的标准字符串变量。这些应该已在您的文本模板中声明。
答案 1 :(得分:2)
不确定您是否要使用列生成代码,但这可能部分有助于回答您的问题(如何提取两个实体之间链接的列名?) ...
NavigationProperty[] foreignKeys = entity.NavigationProperties
.Where(np => np.DeclaringType == entity &&
((AssociationType)np.RelationshipType).IsForeignKey).ToArray();
foreach (NavigationProperty foreignKey in foreignKeys)
{
foreach(var rc in GetSourceSchemaTypes<AssociationType>()
.Single(x => x.Name == foreignKey.RelationshipType.Name)
.ReferentialConstraints)
{
foreach(var tp in rc.ToProperties)
WriteLine(tp.Name);
foreach(var fp in rc.FromProperties)
WriteLine(fp.Name);
}
}
答案 2 :(得分:2)
此代码在我的Visual Studio 2012上运行良好
<#@ template language="C#" debug="true" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#
string inputFile = @"DomainModel.edmx";
MetadataLoader loader = new MetadataLoader(this);
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
foreach (NavigationProperty navProperty in entity.NavigationProperties)
{
AssociationType association = ItemCollection.GetItems<AssociationType>().Single(a => a.Name == navProperty.RelationshipType.Name);
string fromEntity = association.ReferentialConstraints[0].FromRole.Name;
string fromEntityField = association.ReferentialConstraints[0].FromProperties[0].Name;
string toEntity = association.ReferentialConstraints[0].ToRole.Name;
string toEntityField = association.ReferentialConstraints[0].ToProperties[0].Name;
}
}
#>