Этот пост довольно специфичен, но я постараюсь обобщить его как можно больше.
Не обращаясь непосредственно ко всей справочной информации, главный вопрос:
Каков наилучший способ или реализация для проекта API, встроенного в .NET Core 2 и EF Core, для простого повторного использования вашего собственного набора классов POCO, которые ссылаются на сторонние классы POCO, и с повторным использованием я имею в виду, что ваши собственные классы POCO не должны зависеть от сторонних сторон от их свойств класса POCO, но ваши конечные точки по-прежнему должны иметь возможность (легко) получать данные (значения / свойства) из сторонних классов POCO.
Легко написать конечные точки, которые получают поля и значения ваших собственных классов POCO и сторонних классов POCO, используя простой .Include
и убедившись, что ссылочная таблица / класс POCO находится в вашем собственном классе POCO. , Это, однако, также означает, что когда третья сторона становится другой стороной, все конечные точки должны быть переписаны, поскольку новая третья сторона имеет свой собственный набор свойств / классов POCO. Функциональность нашего интерфейса / приложения, тем не менее, более или менее останется прежней, а у сторонних производителей их значения / свойства будут более или менее одинаковыми (хотя названия / настройки для определенных таблиц или столбцов могут отличаться).
Некоторая справочная информация
Я попытаюсь нарисовать текущую ситуацию, как она есть сейчас, для этого я буду использовать наш класс / таблицу Commodity POCO в качестве примера.
Таким образом, наше API-решение, которое вызывается интерфейсным приложением, имеет 2 проекта: проект DAL, в котором размещена вся логика данных / базы данных (Fluent API)
, и сам проект API, в котором находятся конечные точки, модели представления, логика управления пользователями и т. Д. Я максимально упростил это:
![enter image description here](https://i.stack.imgur.com/cJcDu.png)
Все классы таблиц / POCO нашей собственной базы данных находятся в папке OwnModels
, а модели сторонних производителей создаются в папке TheirModels
. Их классы POCO воссоздаются с документом спецификации (файл swagger), который они отправили нам. В нашей базе данных есть несколько таблиц, которые сделаны самим собой, и другой набор таблиц, которые действуют как reference table
между нашей таблицей базы данных и их таблицей, Commodity
- одна из них. У нас запущен процесс, который синхронизирует данные своей базы данных / таблиц с нашей собственной базой данных (в воссозданных таблицах).
В этом примере у них есть таблица с именем TheirCommodity
с 3 полями TheirCommodityID
, Name
и SortOrder
. Теперь мы создали таблицу ссылок (класс POCO) с тем же именем, но без префикса, поэтому Commodity
. В этой таблице есть столбец для собственного идентификатора (CommodityID
) и ссылочного идентификатора их таблицы (ItsCommodityID), в Fluent
это устанавливается как отношение один к одному.
Большинство конечных точек справочных таблиц доступны только для чтения (GET
конечная точка) просто потому, что нам не разрешено изменять / удалять / вставлять данные непосредственно в их таблицы.
Указанные выше товарные таблицы теперь настроены следующим образом:
Их товарный класс POCO:
public class TheirCommodity
{
public TheirCommodity()
{
}
public long TheirCommodityID { get; set; }
public string Name { get; set; }
public long? SortOrder { get; set; }
[JsonIgnore]
public virtual Commodity Commodity { get; set; }
}
Наш (справочный) товарный класс POCO:
public class Commodity
{
public Commodity()
{
}
public long CommodityID { get; set; }
public long TheirCommodityID { get; set; }
public virtual TheirCommodity TheirCommodity { get; set; }
}
Атрибут [JsonIgnore] добавлен, потому что, если нет, он попадает в циклическую ссылку при извлечении данных для нашей таблицы Commodity (оба класса POCO ссылаются на каждую выдру для получения правильного отношения один к одному в FLUENT ).
В API я создал конечную точку GET для этого товара следующим образом:
[HttpGet]
public async Task<IEnumerable<Commodity>> GetCommodities()
{
return await this.Context.Commodity
.Include(i => i.TheirCommodity)
.ToListAsync();
}
Вопрос
Все вышеперечисленное прекрасно работает, но это огромная проблема, когда повторно используйте этот код для другой компании, у которой есть другая третья сторона со своим набором таблиц и свойств.
Эта установка будет означать, что нам придется переписать все наши конечные точки и некоторые другие.Поэтому в идеале, по крайней мере, я думаю (но это также вопрос), вы бы хотели получить все свойства их класса POCO в нашем собственном классе POCO, чтобы мы не зависели (с включением) от их классов POCO. Но это также означает, что вам нужна логика: когда вы получаете значения из их таблиц / свойств, вам нужно написать вспомогательное поле или что-то, что запрашивает таблицу третьей стороны.
Я не могу полностью обернуть голову, как это должно быть достигнуто. Я знаю, что вы не можете написать идеальный кусок кода, который можно использовать повторно (также, поскольку у нас всегда будет шаг к получению сторонних таблиц в вашей собственной базе данных для синхронизации данных), но, по крайней мере, должно быть что-то не нужно переписывать все наши конечные точки.
Мои извинения за большую текстовую стену, но я не мог найти способ написать это короче. А также мои извинения за неправильное использование слов (английский не мой родной язык :))