Как заставить веб-API odatamodelbuilder работать с отображениями EF fluent API

#entity-framework #odata #asp.net-web-api

#entity-framework #odata #asp.net-web-api

Вопрос:

Я создал довольно простую модель предметной области, используя pocos. Я сопоставил их с контекстом EF DB с помощью EntityTypeConfiguration<TEnitityType> классов. Все это работает нормально.

Сейчас я пытаюсь создать конечную точку контроллера OData V4 WebAPI, используя ODataConventionModelBuilder и вот тут-то все и отклеивается. Все работает нормально, пока не столкнется с ассоциацией, не основанной на соглашении. Но я не могу найти способ заставить ODataBuilder получать сопоставления из моих EntityTypeConfiguration<TEnitityType> классов.

Это оставляет мне 2 неприятных варианта

  • Украсьте мои прекрасные чистые pocos грязными атрибутами.
  • Повторно сопоставьте все сопоставления, не основанные на соглашениях, вручную, используя ODataBuilder

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

 var builder = new ODataConventionModelBuilder();

            builder.EntitySet<Item>("Items");
            config.MapODataServiceRoute(
                routeName: "odata",
                routePrefix: "odata",
                model: builder.GetEdmModel(),
                batchHandler: new DefaultODataBatchHandler((GlobalConfiguration.DefaultServer)));

 public class Item
    {
        public Int32 Id { get; set; }

        public Int16 ItemTypeId { get; set; }                   

        public virtual ItemType Type { get; set; }
        public virtual ICollection<ItemVersion> Versions { get; set; }
        public virtual ICollection<ItemTag> Tags { get; set; }     
    }
  

Проблема возникает, когда он сталкивается с коллекцией ItemTags, вот ItemTag:

 public class ItemTag
    {
        public Int32 ItemId { get; set; }

        public string Tag { get; set; }

        public Item Item { get; set; }
    }
  

Который, как вы можете видеть, не основан на соглашениях, и у меня есть класс конфигурации для него следующим образом:

 public class ItemTagConfiguration : EntityTypeConfiguration<ItemTag>
    {
        public ItemTagConfiguration()
        {
            HasKey(x => new {x.ItemId, x.Tag});

            HasRequired(x => x.Item)
                .WithMany(y => y.Tags)
                .HasForeignKey(x => x.ItemId);

        }
    }
  

Кто-нибудь знает способ, которым я могу использовать эти EntityTypeConfiguration файлы с помощью ODataBuilder или web API?

Редактировать

Если найдена эта страница, которая, кажется, указывает, что это может быть возможно с EF 6, который я использую. Что я хочу сделать, так это

 ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Dbf>("Dbfs");
//            modelBuilder.Configurations.Add(new DbfMap());  <---- NO GOOD - Needs Class from DBContext we only have a model builder :(
Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("ODataRoute", "odata", model);
  

но у конструктора нет свойства Configuration.

Комментарии:

1. Fanstatic!, еще немного поискал в Google, и результатом поиска с наивысшим рейтингом для «odata web api fluent data mapping» теперь является этот вопрос SO.

2. Вы когда-нибудь понимали это? Я выплакиваю глаза из-за того же самого.

Ответ №1:

Две вещи:

  1. Теперь я прочитал несколько источников, которые предостерегают от использования отложенной загрузки и сериализации; по сути, это и есть OData; (Он даже использует атрибуты system.runtime.serialization.datacontract и datamember)

  2. Я добился большего успеха в явной загрузке из контекста и определении свойств навигации в modelbuilder для DbContext. Я понимаю, что вы смотрите на настраиваемые свойства навигации, но я совершенно уверен, что это переопределенные методы, полезные для класса ODataModelBuilder (который не требует многого и требует меньше Entity Framework для работы). Где вы уже упоминали использование EF, я полагаю, что это направление, в котором вы будете работать, и если вам не нужно указывать псевдонимы имен ваших моделей, вы добавляете запись для каждого набора, используя условное обозначение.

    EntitySet(«routePrefixName»)

при построении EdmModel, и это связывает отношения, которые вы создали с помощью Fluent ранее. Если вам действительно нужно добавить посторонние элементы в базовую модель, вы должны определить каждый класс как EntityType<>(), установив только ключ. EdmBuilder может использовать мягкие свойства и ассоциацию ключей для присоединения к модели EF в ODataConventionModelBuilder.

Я некоторое время боролся и искал, и, похоже, не существует большого количества информации о .Net OData v4, вероятно, из-за всей проблемы force datetimeoffset.

Надеюсь, это немного поможет