10

我正在使用 EDMX 文件中的 T4 模板生成 POCO(可以说它们是MyEntityObject的子类)。

我有 3 个实体,例如:

  • MyTable1(主键:MyTable1ID)
  • MyTable2(主键:MyTable2ID)
  • MyTable3(主键:MyTable3ID)

这些实体具有以下关系:

MyTable1.MyTable1ID <=> MyTable2.MyTable1ID(MyTable1ID 是 MyTable1 的外键)

MyTable2.MyTable2ID <=> MyTable3.MyTable2ID(MyTable2ID 是 MyTable2 的外键)

或者换个角度看:

我的表 1 <= 我的表 2 <= 我的表 3

我想提取所有外键关系

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";
4

3 回答 3

8

如果您的外键列在概念模型中作为属性公开,则第一个答案有效。此外,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 文件名称的标准字符串变量。这些应该已经在您的文本模板中声明。

于 2011-04-22T19:55:03.500 回答
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);
   }
}
于 2011-04-20T14:47:30.810 回答
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;
    }
}

#>
于 2013-04-09T03:30:13.583 回答