EF4:从 EDMX 的 NavigationProperty 获取链接的列名称

发布于 2024-10-24 03:34:03 字数 1399 浏览 2 评论 0原文

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

我有 3 个实体,例如:

  • MyTable1 (PrimaryKey: MyTable1ID)
  • MyTable2 (PrimaryKey: MyTable2ID)
  • MyTable3 (PrimaryKey: MyTable3ID)

这些实体具有如下关系:

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

I am generating POCOs (lets say they are subclasses of MyEntityObject) by using a T4 template from an EDMX file.

I have 3 entities, e.g.:

  • MyTable1 (PrimaryKey: MyTable1ID)
  • MyTable2 (PrimaryKey: MyTable2ID)
  • MyTable3 (PrimaryKey: MyTable3ID)

These entities have the following relations:

MyTable1.MyTable1ID <=>
MyTable2.MyTable1ID (MyTable1ID is the
foreign key to MyTable1)

MyTable2.MyTable2ID <=>
MyTable3.MyTable2ID (MyTable2ID is the
foreign key to MyTable2)

Or in another view:

MyTable1 <= MyTable2 <= MyTable3

I want to extract all foreign key relations

NavigationProperty[] foreignKeys = entity.NavigationProperties.Where(np => np.DeclaringType == entity && ((AssociationType)np.RelationshipType).IsForeignKey).ToArray();
forewach (NavigationProperty foreignKey in foreignKeys)
{
    // generate code....
}

My Question: How can I extract the column names that are linked between two entities?

Something like this:

void GetLinkedColumns(MyEntityObject table1, MyEntityObject table2, out string fkColumnTable1, out string fkColumnTable2)
{
    // do the job
}

In the example

string myTable1Column;
string myTable2Column;
GetLinkedColumns(myTable1, myTable2, out myTable1Column, out myTable2Column);

the result should be

myTable1Column = "MyTable1ID";
myTable2Column = "MyTable2ID";

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

止于盛夏 2024-10-31 03:34:03

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

The first answer works if your foreign key columns are exposed as properties in your conceptual model. Also, the GetSourceSchemaTypes() method is only available in some of the text templates included with EF, so it is helpful to know what this method does.

If you want to always know the column names, you will need to load the AssociationType from the storage model as follows:

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

In this case, loader is a MetadataLoader defined in EF.Utility.CS.ttinclude and inputFile is a standard string variable specifying the name of the .edmx file. These should already be declared in your text template.

菊凝晚露 2024-10-31 03:34:03

不确定您是否想要使用列生成代码,但这可能部分有助于回答您的问题(如何提取两个实体之间链接的列名称?)...

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

Not sure exactly whether you want to generate code using the columns or not, but this may partly help to answer your question (How can I extract the column names that are linked between two entities?) ...

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);
   }
}
马蹄踏│碎落叶 2024-10-31 03:34:03

这段代码在我的 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;
    }
}

#>

This code works fine on my 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;
    }
}

#>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文