EF4: получить связанные имена столбцов из NavigationProperty EDMX
я генерирую POCOs (скажем, они являются подклассами MyEntityObject) С помощью шаблона T4 из файла EDMX.
у меня есть 3 сущности, например:
- MyTable1 (PrimaryKey: MyTable1ID)
- MyTable2 (PrimaryKey: MyTable2ID)
- MyTable3 (PrimaryKey: MyTable3ID)
эти сущности имеют следующие отношения:
MyTable1.MyTable1ID MyTable2.MyTable1ID (MyTable1ID является внешний ключ к MyTable1)
MyTable2.MyTable2ID MyTable3.MyTable2ID (MyTable2ID является внешний ключ к MyTable2)
или в другом виде:
MyTable1
Я хочу извлечь все отношения внешнего ключа
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";
3 ответов
первый ответ работает, если столбцы внешнего ключа представлены как свойства в концептуальной модели. Кроме того, метод 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-это Метадаталоадер, определенный в ФВ.Полезность.ЦЕЗИЙ.ttinclude и inputFile-это стандартная строковая переменная, указывающая имя .файл edmx. Они уже должны быть объявлены в текстовом шаблоне.
Не уверен, хотите ли вы генерировать код с помощью столбцов или нет, но это может частично помочь ответить на ваш вопрос (Как извлечь имена столбцов, которые связаны между двумя объектами?) ...
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);
}
}
этот код отлично работает в моей 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;
}
}
#>