У меня ошибка в объявлении этого класса:
public class MenuItemEstablishmentsRepository : VeganItemEstablishmentsRepository<MenuItem, Restaurant, MenuItemTag>
{
Ошибка:
Тип Vepo.Domain.MenuItem нельзя использовать в качестве параметра типа 'TVeganItem' в универсальном типе или методе 'VeganItemEstablishmentsRepository<TVeganItem, TEstablishment, TVeganItemTag>'. Нет неявного преобразования ссылок из 'Vepo.Domain.MenuItem' для 'Vepo.Domain.VeganItem<Vepo.Common.Enums.MenuItemTag, Vepo.Domain.VeganItemEstablishment<Vepo.Domain.MenuItem, Вепо.Домен.Ресторан>>'. [Вепо.Данные]
MenuItem
и VeganItem
:
[ElasticsearchType(RelationName = "menuitem", IdProperty = "Id")]
public class MenuItem : VeganItem<MenuItemTag, MenuItemEstablishment>
{
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Nest;
using Newtonsoft.Json;
namespace Vepo.Domain
{
[Serializable]
public abstract class VeganItem<TVeganItemTag, TVeganItemEstablishment> : DomainEntity<int>
{
[Required]
public string Name { get; set; }
[Required]
public string CompanyName { get; set; }
[Required]
public string Description { get; set; }
public string Image { get; set; }
[Required]
public int IsNotVeganCount { get; set; } = 0;
[Required]
public int IsVeganCount { get; set; } = 0;
[Required]
public int RatingsCount { get; set; } = 0;
[Required]
public int Rating { get; set; }
[Required]
public List<TVeganItemTag> Tags { get; set; }
[PropertyName("veganItemEstablishments", Ignore = true)]
public virtual ICollection<TVeganItemEstablishment> VeganItemEstablishments { get; set; }
}
}
Почему он не может преобразовать MenuItem
в VeganItem
, когда MenuItem
наследуется от VeganItem
? Как обойти эту ошибку?
Суперрепозиторий:
public abstract class VeganItemEstablishmentsRepository
<TVeganItem, TEstablishment, TVeganItemTag> :
Repository<VeganItemEstablishment<TVeganItem, TEstablishment> int>
where TVeganItem : VeganItem<TVeganItemTag, VeganItemEstablishment<TVeganItem, TEstablishment>>
where TEstablishment : Establishment<VeganItemEstablishment<TVeganItem, TEstablishment>>
Почему в репозитории есть только сложные ограничения
where
? Если единственный действительныйVeganItem
также имеет ограничениеVeganItemEstablishment
, почему бы не определить это правило для элемента? Но действительно ли вам нужны эти сложные ограничения?@JeremyLakeman Я не знаю, нужны ли мне ограничения
where
. Я заметил, что когда я добавлял ограничения вVeganItem
, это означало, что мне нужно было передать больше типов вVeganItem
, поэтому это выглядело неуклюжим. Мы не можем использовать абстрактные классы в таблицах, верно? Вот почему я думаю, что мне нужны все эти универсальные типы, если я хочу сделать код пригодным для повторного использования.Сколько похожих, но немного разных таблиц вы создаете? Как вы планируете запрашивать их? Это не похоже на хороший дизайн реляционной базы данных.
@JeremyLakeman Запросы к ним кажутся простыми, поскольку все они наследуются от одного и того же суперкласса, я могу ввести их как суперкласс (но я разработчик интерфейса, поэтому я могу ошибаться). Но да, я думаю, что мне не нужны все эти подклассы. Подклассы очень похожи. Они отличаются только тем, что
tags
— это другое перечисление. Может быть, я должен сделать это int? Я также подумал, что этот дизайн позволит мне изменять их по мере развития приложения, которое может быть более гибким.@JeremyLakeman в будущем может быть до 20 подклассов VeganItem. Но, может быть, я мог бы сделать VeganItem конкретным классом и просто использовать его, звучит ли это разумно, если они так похожи?
Не пытайтесь сделать схему слишком гибкой, просто постарайтесь соответствовать сегодняшним требованиям. ЯГНИ. Если вы используете таблицу на уровне наследования, вы можете добавить необязательные столбцы базы данных, которые сопоставляются только с одним подклассом. Должны ли теги быть перечислением? Вы действительно хотите перекомпилировать, когда клиент хочет новое имя тега?
Каково определение
MenuItemEstablishment
?По сути, если
MenuItemEstablishment
не наследует напрямую отVeganItemEstablishment<MenuItem, Restaurant>
, вы сталкиваетесь с желанием иметь ковариантный универсальный тип в ситуации, когда ваши универсальные типы инвариантны. Если какой-либо из параметров универсального типа для VeganItemEstablishment в большей или меньшей степени является производным от MenuItem или Restaurant, он не соответствует определению инварианта и не будет разрешен.@JeremyLakeman У меня возникли проблемы с избавлением от некоторых ненужных подклассов. Как получить две таблицы одного типа? У меня есть 2 таблицы, содержащие
tags
типаGroceryItemTag
иMenuItemTag
. У них в основном есть 3 поля, одно из которых было перечислением. Я создал новый класс с именемOption
, где предыдущее перечисление теперь представляет собой просто int, но мне нужна таблица с именамиMenuItemTags
иGroceryItemTags
, оба типаOption
.Если вы собираетесь упростить схему, напишите sql-скрипт миграции для перемещения данных.
@JeremyLakeman Спасибо, я просто удалил таблицы и создал новую миграцию (приложение еще не запущено). Но я все еще получаю: начальный объект для типа объекта «Option» не может быть добавлен, потому что другой начальный объект со значением ключа «Id: 0» уже добавлен. Я думаю, это новый вопрос :)