【问题标题】:Access Association Details of NavigationPropertyNavigationProperty 的访问关联详细信息
【发布时间】:2012-07-27 20:44:50
【问题描述】:

我正在创建一个 C# T4 模板来构建一些基于 .edmx 文件的类,到目前为止一切顺利。不过,我现在需要的是一种通过NavigationProperty 访问它在数据库中连接的列名称的方法。

不久前,我意识到您可以在 .edmx 可视化设计器中访问此信息,位于特定 NavigationProperty 的映射详细信息下:

基本上,如果在 T4 模板中;我已经有一个我想要的 NavigationProperty 实例...如何获取它连接的字段的名称? (在这种情况下为WeatherOnMondays)

【问题讨论】:

  • 尽管这个问题的方法比我的要简单得多,但答案确实对我有用,如果你愿意回答,我可以给你加分:)。
  • 必须输入代码,因此它不会自动转换为评论。谢谢,祝 t4 好运,我玩得很开心。
  • 你可以从我正在做的项目中查看源代码t4csla.codeplex.com,也许你会发现一些有用的东西。

标签: c# entity-framework t4 scaffolding


【解决方案1】:

答案来自:EF4: Get the linked column names from NavigationProperty of an EDMX

实现此目的的两种方法:

// 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));

第二种方法:

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);
   }
}

【讨论】:

  • 请注意,这在 EF 使用幕后交叉引用表在两个 DBSet 之间创建多对多关系的情况下不起作用。 navProp.RelationshipType.Name 将解析为交叉引用表的名称,而不是包含必填字段名称的 FK,因此 AssociationType 对象将没有 ReferentialConstraints。
  • @MCattle 是的,我不喜欢 EF 处理多对多的方式,希望也可以选择包含表格。我曾经在没有 FK 的情况下添加它们并手动处理它们,或者我在交叉引用表中添加了另一列以使其在 EF 中生成。第三种选择是编辑 T4,但随后您将丢失更新。此外,这段代码在 EF7 中会简单得多,因为它有 API。
【解决方案2】:

如果您有NavigationProperty,则它连接的字段由属性ToEndMember 和FromEndMember 表示

【讨论】:

  • 但我不知道如何获取它正在连接的数据库列的名称(如图所示)。
【解决方案3】:

这段代码更简单。它在我的 Visual Studio 2012 上运行良好。AssociationType 类的详细信息可以在 http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.associationtype.aspx 和 http://msdn.microsoft.com/en-us/library/system.data.metadata.edm.referentialconstraint.aspx 。

<#@ 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;
    }
}

#>

【讨论】:

    【解决方案4】:

    请参阅http://brewdawg.github.io/Tiraggo.Edmx/,您可以从 NuGet 安装它。它提供 edmx 文件中的所有元数据,包括所有映射、每列的低级 SQL 数据类型,所有这些东西,看看页面上的示例,你会发现它是多么容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      相关资源
      最近更新 更多