Программно получить состояние «Nullable» свойства в Entity Framework

Мне нужно получить свойство Nullable для поля в EF. Некоторый магический код должен быть выполнен для свойств, которые имеют значение Nullable=True, и я не могу найти работающее решение для получения свойства.

foreach (PropertyInfo property in (PropertyInfo[])type.GetProperties())
{
   var getPropertyType = property.GetMethod.ReturnTypeCustomAttributes.ToString();

   var getValue = property.GetValue(model);
   bool isNullable = property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);

   // isNullable always returns false !!!! and I need it to return true if the field is allowed to be null

   if ((getValue == null) && (!isNullable))
   {
   }
}

Сорт

//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace testApp.Data
{
    using System;
    using System.Collections.Generic;

    public partial class Person
    {
        public int PersonId { get; set; }
        public string Email { get; set; }
    }
}

Любая помощь будет оценена по достоинству.


person DJJ    schedule 09.04.2015    source источник
comment
Пожалуйста, опубликуйте класс, который представляет переменную type — будет полезно увидеть, какие свойства вы ожидаете обнулить. В настоящее время код выглядит хорошо (существующее подозрение заключается в том, что GetProperties по умолчанию будет возвращать только все общедоступные свойства, поэтому я подозреваю, что ваши свойства Nullable не являются общедоступными)   -  person Rich O'Kelly    schedule 09.04.2015
comment
Поправьте меня, если я ошибаюсь, но Nullable=True в Entity Framework не дает вам System.Nullable<type>. Возможный ответ: http://stackoverflow.com/questions/18710697/how-to-check-if-a-property-of-an-entity-framework-type-is-nullable   -  person freedomn-m    schedule 09.04.2015
comment
@rich.okelly Я вижу свойство в отладке и получаю его значение и тип данных, поэтому я считаю, что проблема не в этом.   -  person DJJ    schedule 09.04.2015
comment
@freedomn-m это то, что я «не хочу делать», так как у меня огромный edmx и я не хочу определять каждое поле, как сказано в посте, а просто хочу получить состояние, допускающее значение NULL, в соответствии со структурой БД.   -  person DJJ    schedule 09.04.2015
comment
@DJJ, не могли бы вы опубликовать урок, пожалуйста?   -  person Rich O'Kelly    schedule 09.04.2015
comment
@rich.okelly Я добавил класс-заглушку, сгенерированный из модели инфраструктуры сущностей. Помните, что в средстве просмотра моделей в таблице есть свойства, в которых вы можете установить состояние nullable для каждого свойства, и это не будет отображаться в классе.   -  person DJJ    schedule 10.04.2015


Ответы (2)


Итак, вам нужны свойства, которые могут быть обнулены в базе данных. Это означает, что «какой-то волшебный код» должен изучить модель хранения EDMX. Модель классов не содержит этой информации, не говоря уже о сгенерированных классах.

Вот как можно получить список всех свойств, допускающих значение NULL, в модели хранения:

var tableName = "someTable";
var oc = ((IObjectContextAdapter)context).ObjectContext;

var items = oc.MetadataWorkspace.GetItems(DataSpace.SSpace).OfType<EntityType>();
foreach (var entityType in items.Where(e => e.Name == tableName))
{
    var props = string.Join(",", entityType.Properties.Where(p => p.Nullable));
    Debug.WriteLine(string.Format("{0}: {1}", entityType.Name, props));
}
person Gert Arnold    schedule 10.04.2015
comment
Спасибо за отзыв. Где бы я заменил или указал конкретный объект, на который я смотрю? Я попытался добавить lamda exp в конец элементов на основе свойства Name, но безуспешно. Решение будет работать в худшем случае, но у меня есть почти 700 таблиц, которые нужно запустить для каждого, а затем проверить указанную таблицу. - person DJJ; 10.04.2015
comment
При просмотре модели хранения entityType.Name равно имени таблицы. Не могли бы вы использовать это в качестве входных данных? - person Gert Arnold; 10.04.2015
comment
Да, вы могли бы, но с точки зрения эффективности цикл будет выполняться почти 700 раз для каждого объекта сущности в базе данных, поэтому возникает вопрос о фильтрации элементов, установленных для необходимого объекта. - person DJJ; 10.04.2015
comment
Ваш мужчина!!!!! Спасибо, мистер. Я переместил лямбу в строку элементов, чтобы вывести таблицу, а затем проверил каждое соответствующее свойство на наличие нулевого состояния, полностью удалив цикл foreach. var items = oc.MetadataWorkspace.GetItems(DataSpace.SSpace).OfType‹EntityType›(). Где(e => e.Name == someTable).SingleOrDefault(); var getProperty = items.Properties[someProperty].Nullable; - person DJJ; 10.04.2015
comment
DJJ Я рад, что это у вас получилось -- до сих пор качаю головой, что в сгенерированном коде нет какого-то проявления этого свойства -- так что приходится обращаться к модели хранения (или БД себе) для получения этой информации. И если вы этого не сделали, вы получите ошибку времени выполнения. - person Gerard ONeill; 10.09.2015

Для этого можно использовать метод Nullable.GetUnderlyingType.

if (Nullable.GetUnderlyingType(propertyType) != null)
{
    // It's nullable
}
person Saagar Elias Jacky    schedule 09.04.2015
comment
Это делает по существу тот же вызов, что и GetGenericTypeDefinition() == typeof(Nullable<>), и возвращает базовый тип, который будет тем, что находится внутри ‹› (например, Nullable‹int› дает int) - person freedomn-m; 09.04.2015
comment
да, и это то, что он говорит ... если вы получаете базовое свойство для Nullable как NOT NULL, это означает, что это Nullable.... Если вы ничего не получаете, это не Nullable... - person Saagar Elias Jacky; 09.04.2015
comment
Теперь вижу - спасибо за разъяснение. GetGenericTypeDefinition() выдает ошибку, если она не обнуляема, но это не так. - person freedomn-m; 09.04.2015
comment
Пробовал, и он по-прежнему возвращает false (что означает, что он не может быть нулевым), даже если для свойства установлено значение null в db. - person DJJ; 09.04.2015