18

EF-CodeFirst 5 (dll ver 4.4.0.0、.net 4.0) を使用するアプリケーションがあります。

特定のエントリ タイプについて次の情報を取得できるように、エンティティ メタデータを読み取ることができる必要があります。

  • 1 対多の関係 (参照エンティティ) であるプロパティ
  • どのプロパティが多対一の関係であるか (現在のエンティティを参照するエンティティのコレクション)
  • これも素晴らしいですが、絶対に必要というわけではありません: どのプロパティが多対多の関係 (関係の集まり) であるか

プロパティのリストに foreach ループを記述し、すべての参照が仮想であることに依存してそれらを「認識する」ことで、この情報を取得できますが、それは「適切な」方法ではないと感じています。その情報をxml形式で提供できることは知っていEdmxWriterますが、公開されていないInternalContextにアクセスすることでそうし、そのxmlを使用せずに厳密に型指定されたリスト/配列を直接取得したいと考えています。どの API を使用すればよいですか (このための API がある場合、それを見つけることができないようです)。

4

1 に答える 1

27

Gorane、これで始められるはずです...
(私はあまり遊んでいません-デバッガーで少し実験して、どのプロパティ/情報とそれを取得するかを確認する必要があります)

using (var db = new MyDbContext())
{
    var objectContext = ((IObjectContextAdapter)db).ObjectContext;
    var container = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace);
    foreach (var set in container.BaseEntitySets)
    {
        // set.ElementType.
        foreach (var metaproperty in set.MetadataProperties)
        {
            // metaproperty.
        }
    }

    // ...or... 

    var keyName = objectContext
        .MetadataWorkspace
        .GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace)
        .BaseEntitySets
        .First(meta => meta.ElementType.Name == "Question")
        .ElementType
        .KeyMembers
        .Select(k => k.Name)
        .FirstOrDefault();
}

より具体的には...

foreach (var set in container.BaseEntitySets)
{
    var dependents = ((EntitySet)(set)).ForeignKeyDependents;
    var principals = ((EntitySet)(set)).ForeignKeyPrincipals;
    var navigationProperties = ((EntityType)(set.ElementType)).NavigationProperties;
    foreach (var nav in navigationProperties)
    {
        // nav.RelationshipType;
    }
}

これらのプロパティの一部は「一般大衆」に公開されていないように見えるため、リフレクションを使用するか、よりスマートな方法を見つける必要がありますが、かなりの情報がそこにあります.



そして、これらのリンクの詳細情報...

EF4 でエンティティの最初の EntityKey 名を取得する方法

EF4 エンティティのプロパティのデータベース テーブルと列名を抽出するにはどうすればよいですか?


EDIT : navigationProperties のリストを出発点として使用すると、次のように必要なものがすべて得られました。

        ManyToManyReferences = navigationProperties.Where(np =>
            np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many &&
            np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
            .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
            .ToList();

        OneToManyReferences = navigationProperties.Where(np =>
            (np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One ||
            np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne) &&
            np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
            .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
            .ToList();

        ManyToOneReferences = navigationProperties.Where(np =>
            np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many &&
            (np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One ||
            np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne))
            .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
            .ToList();

        OneToOneReferences = navigationProperties.Where(np =>
            np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One &&
            np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One)
            .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name))
            .ToList();

CreateLambdaExpression メソッドは私の礼儀ではありません。クレジットは Jon Skeet に送られます。コードはこの回答の助けを借りて作成されました

ここに私の CreateLambdaExpression メソッドがあります:

public static Expression<Func<TEntity, object>> CreateLambdaExpression<TEntity>(string propertyName)
{
    ParameterExpression parameter = Expression.Parameter(typeof (TEntity), typeof (TEntity).Name);
    Expression property = Expression.Property(parameter, propertyName);

    return Expression.Lambda<Func<TEntity, object>>(property, new[] {parameter});
}
于 2013-03-30T15:37:44.360 に答える