16

私はEF4と、MaxLength次のようなエンティティから値を取得するために見つけたコードを使用していました。

public static int? GetMaxLength(string entityTypeName, string columnName)
        {
            int? result = null;
            using (fooEntities context = new fooEntities())
            {
                Type entType = Type.GetType(entityTypeName);
                var q = from meta in context.MetadataWorkspace.GetItems(DataSpace.CSpace)
                                  .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
                        from p in (meta as EntityType).Properties
                        .Where(p => p.Name == columnName
                                    && p.TypeUsage.EdmType.Name == "String")
                        select p;

                var queryResult = q.Where(p =>
                {
                    bool match = p.DeclaringType.Name == entityTypeName;
                    if (!match && entType != null)
                    {
                        match = entType.Name == p.DeclaringType.Name;
                    }

                    return match;

                }).Select(sel => sel.TypeUsage.Facets["MaxLength"].Value);
                if (queryResult.Any())
                {
                    result = Convert.ToInt32(queryResult.First());
                }

                return result;
            }
        }

ただし、EF5にアップグレードしたところ、次のエラーメッセージが表示されることがわかっています。

...fooEntities'  does not contain a definition for 'MetadataWorkspace' and no
extension method 'MetadataWorkspace' accepting a first argument of type
'...fooEntities' could be found (are you missing a using directive or an assembly
 reference?)

EF5からそのメタデータを取得するための最良の方法は何ですか?

4

4 に答える 4

30

これは非常に便利なコードです。少しリファクタリングしたので、ここに投稿しようと思ったのでとても便利です。

public static int? GetMaxLength<T>(Expression<Func<T, string>> column)
    {
        int? result = null;
        using (var context = new EfContext())
        {
            var entType = typeof(T);
            var columnName = ((MemberExpression) column.Body).Member.Name;

            var objectContext = ((IObjectContextAdapter) context).ObjectContext;
            var test = objectContext.MetadataWorkspace.GetItems(DataSpace.CSpace);

            if(test == null)
                return null;

            var q = test
                .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
                .SelectMany(meta => ((EntityType) meta).Properties
                .Where(p => p.Name == columnName && p.TypeUsage.EdmType.Name == "String"));

            var queryResult = q.Where(p =>
                                          {
                                              var match = p.DeclaringType.Name == entType.Name;
                                              if (!match)
                                                  match = entType.Name == p.DeclaringType.Name;

                                              return match;

                                          })
                .Select(sel => sel.TypeUsage.Facets["MaxLength"].Value)
                .ToList();

            if (queryResult.Any())
                result = Convert.ToInt32(queryResult.First());

            return result;
        }
    }

そして、あなたはそれを次のように呼ぶことができます:

GetMaxLength<Customer>(x => x.CustomerName);

これは、CustomerタイプのDbContextで定義されたDbSetがあり、MaxLengthが定義されたCustomerNameのプロパティを持っていることを前提としています。

これは、テキストボックスのmaxlengthをデータベース内のフィールドの最大長に設定するModel属性を作成する場合などに非常に役立ち、常に2つが同じであることを確認します。

于 2012-10-18T22:18:59.027 に答える
11

mccow002の例をコピーアンドペースト対応のExtensionメソッドクラスにリファクタリングしました。

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Metadata.Edm;

public static class DbContextExtensions
{

    // get MaxLength as an extension method to the DbContext
    public static int? GetMaxLength<T>(this DbContext context, Expression<Func<T, string>> column)
    {
        return (int?)context.GetFacets<T>(column)["MaxLength"].Value;
    }

    // get MaxLength as an extension method to the Facets (I think the extension belongs here)
    public static int? GetMaxLength(this ReadOnlyMetadataCollection<Facet> facets)
    {
        return (int?)facets["MaxLength"].Value;            
    }

    // just for fun: get all the facet values as a Dictionary 
    public static Dictionary<string,object> AsDictionary(this ReadOnlyMetadataCollection<Facet> facets) {
        return facets.ToDictionary(o=>o.Name,o=>o.Value);
    }


    public static ReadOnlyMetadataCollection<Facet> GetFacets<T>(this DbContext context, Expression<Func<T, string>> column)
    {
        ReadOnlyMetadataCollection<Facet> result = null;

        var entType = typeof(T);
        var columnName = ((MemberExpression)column.Body).Member.Name;

        var objectContext = ((IObjectContextAdapter)context).ObjectContext;
        var test = objectContext.MetadataWorkspace.GetItems(DataSpace.CSpace);

        if (test == null)
            return null;

        var q = test
            .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
            .SelectMany(meta => ((EntityType)meta).Properties
            .Where(p => p.Name == columnName && p.TypeUsage.EdmType.Name == "String"));

        var queryResult = q.Where(p =>
        {
            var match = p.DeclaringType.Name == entType.Name;
            if (!match)
                match = entType.Name == p.DeclaringType.Name;

            return match;

        })
            .Select(sel => sel)
            .FirstOrDefault();

        result = queryResult.TypeUsage.Facets;

        return result;

    }

}
于 2014-04-04T20:44:33.987 に答える
10

これは、EFをアップグレードしただけでなく、APIも変更したことを意味します。APIには、コアObjectContextAPIと簡略化されたDbContextAPIの2つがあります。コードはObjectContextAPI(EF4で使用可能な唯一のAPI)に依存していますが、EF5はDbContext API(EF4.1以降に別のEntityFramework.dllアセンブリで追加)を使用しています。新しいEF機能と以前のコードを使用する場合は、.NET4.5にアップグレードする必要があります。

新しいAPIも使用する場合は、既存のコードの多くを更新する必要がありますが、それでもメソッドを取得ObjectContextDbContextて再度機能させることは可能です。このスニペットを使用する必要があります:

var objectContext = ((IObjectContextAdapter)context).ObjectContext;

objectContextコードの代わりに使用contextします。

于 2012-09-12T08:18:53.523 に答える
0

私にも同様の問題があり、解決策はここにあります。

  MyDBEntities ctx = new MyDBEntities();
        var objectContext = ((IObjectContextAdapter)ctx).ObjectContext;

        var cols = from meta in objectContext.MetadataWorkspace.GetItems(DataSpace.CSpace)
                   .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
                   from p in (meta as EntityType).Properties
                      .Where(p => p.DeclaringType.Name == "TableName")
                   select new
                   {
                       PropertyName = p.Name                          
                   };
于 2014-03-08T00:43:13.693 に答える