Репозиторий EntityFramework, все строки возвращают нулевые значения

Сводка

Я изменил решение nopCommerce, включив в него новую сущность с подходом CodeFirst, оно успешно обновило базу данных, как показано на изображении ниже.

Фото с обновленной таблицей базы данных

Когда я пытаюсь получить доступ к таблице репозитория, которая вставляется через AutoFrac, я получаю строки, возвращаемые репозиторием, но все столбцы содержат нулевые значения. Обратите внимание, что количество строк в таблице такое же, как и в таблице базы данных, поэтому кажется, что она подключена, но значения не отображаются.

Код, вызывающий репозиторий

{
    public partial class NutrientService : INutrientService
    {
        #region fields

        protected readonly IRepository<ProductNutrient> _productNutrientRepository;

        #endregion fields

        #region Ctor

        public NutrientService(IRepository<ProductNutrient> productNutrientRepository)
        {
            _productNutrientRepository = productNutrientRepository;
        }

        #endregion Ctor

        public IList<ProductNutrient> GetNutrients()
        {
            var query = from p in _productNutrientRepository.Table
                        select p as ProductNutrient;
            var list = query.ToList();
            return list;
        }

        public IList<ProductNutrient> GetNutrientsByProductID()
        {
           
            var query = from p in _productNutrientRepository.Table
                        select p as ProductNutrient;
            var list = query.ToList();
            return list;
        }
    }
} 

Отладка, показывающая нулевые значения, возвращаемые из репозитория

Определение таблицы в SQL Management Studio

Определение сущности в коде

    public class ProductNutrient : BaseEntity
    {
        public int NutrientID;

        public int ProductID;

        public string Nutrient;

        public bool ShowLessThan;

        public decimal Value;

        public string Unit;
    }
}

Репозиторий работает с другими таблицами, но в любом случае вот код репозитория

      /// </summary>
        public virtual IQueryable<TEntity> Table => Entities;

        /// <summary>
        /// Gets an entity set
        /// </summary>
        protected virtual ITable<TEntity> Entities => _entities ?? (_entities = _dataProvider.GetTable<TEntity>());


        #endregion
    }

person DanCRichards    schedule 06.01.2021    source источник
comment
Пожалуйста, не размещайте код и результаты в виде изображений. Их нельзя скопировать (частично) для ответа и их текст не появится в поисковых системах. Изображения следует использовать только в крайнем случае.   -  person Gert Arnold    schedule 07.01.2021
comment
Обновил спасибо. Это мой первый пост в SO. Я надеюсь, что вы также можете оказать некоторую поддержку в этом вопросе. Спасибо Дэн   -  person DanCRichards    schedule 07.01.2021
comment
select p as ProductNutrient;, вероятно, делает не то, что вы думаете, p это что-то другое. А зачем тебе это бросать? Но репозиторий нам не виден (особенно что там за _productNutrientRepository.Table) и, тем не менее, вопрос можно задать без всех картинок.   -  person Gert Arnold    schedule 07.01.2021
comment
Мне было интересно, что это за _productNutrientRepository.Table? Не могли бы вы показать нам код _productNutrientRepository и код таблицы?   -  person Serge    schedule 07.01.2021
comment
Привет, @Sergey, я обновил пост, чтобы показать это. В моем проекте есть и другие сервисы, которые ссылаются на интерфейс репозитория и прекрасно работают. Я немного смущен тем, почему _productNutrientRepository.Table будет отображать элементы в списке, но с нулевыми значениями. Также происходит, когда я вставляю значения, он просто создает нулевые записи.   -  person DanCRichards    schedule 07.01.2021
comment
@GertArnold Вам, вероятно, не нужно беспокоиться о том, чтобы помочь мне в этом, спасибо!   -  person DanCRichards    schedule 07.01.2021


Ответы (1)


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

Начните с того, что избавьтесь от всех своих абстракций, превратившись в репозиторий. Вместо этого введите DbContext в качестве отправной точки:

protected readonly AppDbContext _context = null;

public NutrientService(AppDbContext context)
{
    _context = context ?? throw new ArgumentNullException("context");
}

public IList<ProductNutrient> GetNutrients()
{
    var productNutrients = context.ProductNutrients
        .ToList();

    return productNutrients;
}

Это возвращает полные данные или пустые значения? Если он все еще пуст, вам нужно проверить строку подключения, которая используется во время выполнения, поскольку она, возможно, указывает на более старый экземпляр базы данных, чем тот, на который вы сейчас смотрите. Кажется, это довольно распространенная проблема, когда люди используют SSMS или дизайнеров для просмотра схемы БД, но затем среда выполнения web/app.config указывает на более старое или совместно используемое расположение БД или на сгенерированную БД, в которой есть некоторые данные. , но не то, что вы ожидаете увидеть.

Если он возвращает ожидаемые данные, значит, ваша абстракция (репозиторий) каким-то образом ошибочна. Первый вопрос: почему вы реализуете репозиторий вокруг DbContext? Мой совет, когда дело доходит до репозиториев, заключается в том, что общие репозитории, т.е. Repository<ProductNutrient> — очень плохой анти-шаблон. Если вы реализуете репозиторий, потому что столкнулись с его примером, вам необходимо понять основную причину этого. Если вы внедряете репозиторий, чтобы скрыть тот факт, что вы используете EntityFramework или скрываете DbContext, то ИМХО это неправильная причина для реализации репозитория. Единственная причина рассмотреть возможность реализации шаблона репозитория поверх EntityFramework — упростить модульное тестирование вашего кода. При этом я настоятельно рекомендую использовать IQueryable<TEntity> в качестве возвращаемых типов. Возможно, что .Table возвращает IQueryable<ProductNutrient>, но если он возвращает DbSet<ProductNutrient>, вы можете просто использовать DbContext. Если он возвращает что-то вроде IEnumerable<ProductNutrient>, то вы потенциально оставляете свою систему открытой для значительных ограничений производительности в будущем, поскольку вы теряете большинство возможностей, которые может предоставить EF.

Если вы не планируете использовать модульные тесты, где вам нужно будет имитировать уровень данных, чтобы тесты получали надежное известное состояние, то на самом деле нет никаких оснований создавать классы репозитория и потенциально налагать очень дорогостоящие ограничения на ваш доступ к данным. Я описываю проблемы с шаблоном Generic Repository и EF в своем ответе на этот вопрос: (Как установить несколько служб из Entity Framework Core в шаблоне репозитория?) Вы можете полностью протестировать код, использующий DbContext, с помощью специального образа базы данных интеграционного теста, или в базе данных в памяти, или с немного большей работой, издеваясь над DbContext/DbSets. Для модульных тестов, которые многократно запускаются во время разработки до интеграции, имитация класса Repository намного проще.

person Steve Py    schedule 06.01.2021
comment
Спасибо за вашу помощь, просмотр DBContext решил проблему. Отказ от модели репо не стоит того, я работаю над фреймворком OpenSource, который использует ее, и тратить время на изменение всего этого не принесет значительной пользы, чтобы гарантировать его изменение. - person DanCRichards; 08.01.2021