Подтвердить что ты не робот

Структура сущности 5 MaxLength

Я использовал 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?

4b9b3361

Ответ 1

Это означает, что вы не только обновили EF, но и изменили API. Существует два API - основной API ObjectContext и упрощенный API DbContext. Ваш код зависит от ObjectContext API (единственный API, доступный в EF4), но EF5 использует DbContext API (добавляется в отдельную сборку EntityFramework.dll с EF4.1). Если вы хотите использовать новые функции EF и свой предыдущий код, вы должны просто перейти на .NET 4.5.

Если вы также хотите использовать новый API, вам придется обновить много вашего существующего кода, но все же можно получить ObjectContext от DbContext и снова заставить ваш метод работать. Вам просто нужно использовать этот фрагмент:

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

и используйте ObjectContext вместо context в вашем коде.

Ответ 2

Это очень удобный фрагмент кода. Я немного переработал его, и он настолько полезен, что я думал, что разместил его здесь.

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

Предполагается, что у вас есть DbSet, определенный в вашем DbContext типа Customer, который имеет свойство CustomerName с определенной MaxLength.

Это очень полезно для таких вещей, как создание атрибутов модели, которые устанавливают максимальную длину текстового поля в максимальную длину поля в базе данных, всегда гарантируя, что два одинаковые.

Ответ 3

Я реорганизовал пример mccow002 в класс метода расширения:

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;

    }

}

Ответ 4

У меня была аналогичная проблема и решение здесь;

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