Отображение IQueryable для модели домена для OData в .NET - PullRequest
0 голосов
/ 11 июня 2018

Недавно я реализовал OData в своем веб-API ASP .NET Core.Я добился успеха, пока возвращаю модели баз данных напрямую.Однако у меня возникают проблемы, как только я пытаюсь вернуть модели предметной области.

Основная проблема заключается в сопоставлении класса данных с классом домена при сохранении типа возвращаемого значения IQueryable.Хотя я нашел частичный успех при использовании метода расширения MapTo в AutoMapper, я обнаружил, что мне не удается использовать метод $ extended для расширения коллекции объектов, которые также являются объектами домена.

Я создал пример проекта для иллюстрацииЭта проблема.Вы можете просмотреть или скачать полный проект на github здесь .Смотрите описание ниже.

С учетом следующих двух классов баз данных:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public ICollection<Order> Orders { get; set; }

    public Product() {
        Orders = new Collection<Order>();
    }
}

public class Order
{
    public int Id { get; set; }
    public Double Price { get; set; }  
    public DateTime OrderDate { get; set; }

    [Required]
    public int ProductId { get; set; }
    public Product Product { get; set; }    
}

и следующих моделей доменов ...

public class ProductEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public ICollection<OrderEntity> Orders { get; set; }
}

public class OrderEntity
{
    public int Id { get; set; }
    public Double Price { get; set; }
    public DateTime OrderDate { get; set; }

    [Required]
    public int ProductId { get; set; }
    public Product Product { get; set; }
}

И контроллера продуктов

public class ProductsController
{
    private readonly SalesContext context;

    public ProductsController(SalesContext context) {
        this.context = context;
    }   

    [EnableQuery]
    public IQueryable<ProductEntity> Get() {
        return context.Products
            .ProjectTo<ProductEntity>()
            .AsQueryable();
    }
}

Все следующие запросы OData проходят:

Следующееоднако запрос не проходит:

HTTP-ответ никогда не возвращается.Единственное сообщение об ошибке, которое я получаю, приходит с консоли:

System.InvalidOperationException: Sequence contains no matching element at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)

Наконец, вот ссылка на профиль сопоставления:

    public static class MappingProfile
{
    public static void RegisterMappings() {
        Mapper.Initialize(cfg =>
        {
           cfg.CreateMap<Order, OrderEntity>();
           cfg.CreateMap<Product, ProductEntity>();
        });
    }
}

Я могу решить проблему, просто возвратив Listвместо IEnumerable в контроллере, но это, конечно, вызовет большой запрос к базе данных, который будет требовать высокой производительности.

Как указано выше, вы можете найти ссылку на полный проект на Github здесь .Дайте мне знать, если найдете ответы!

1 Ответ

0 голосов
/ 29 мая 2019

Мне удалось заставить это работать с несколькими небольшими ревизиями.

Обновление моделей домена:

public class ProductEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public ICollection<Order> Orders { get; set; }
}

public class OrderEntity
{
    public int Id { get; set; }
    public double Price { get; set; }
    public DateTime OrderDate { get; set; }

    [Required]
    public int ProductId { get; set; }
    public Product Product { get; set; }
}

Включение расширения вручнуюпостроитель маршрута:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, SalesModelBuilder modelBuilder)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseMvc(routeBuilder =>
        {
            routeBuilder.Expand().Select();
            routeBuilder.MapODataServiceRoute("ODataRoutes", "odata",
                    modelBuilder.GetEdmModel(app.ApplicationServices));
        });
}

Использование следующих запросов:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...