Как добавить EntitySet при использовании Breeze EdmBuilder

ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: я поставлю ответ здесь вверху для других людей, которые ищут. Основная проблема заключалась в несоответствии пространства имен, вызванном тем, что db-first сгенерировал EDM, присоединив «.Models» к концу пространства имен модели. Это пространство имен не соответствовало пространству имен odata, поэтому маршрут не работал. Я только что удалил все вхождения «.Models» из пространства имен, и теперь это работает.


Новичок пробует Breeze с настройкой webApiOdata. Извините, если этот вопрос тривиален.

У меня есть модель edmx, сгенерированная базой данных, с контроллерами webapi odata. У меня были проблемы с отображением правильных метаданных, пока я не прочитал о новом Breeze EdmBuilder.

Это решило проблему отображения правильных метаданных, но теперь я не могу перейти ни к одной из таблиц. Если я попробую /odata/Customers, я получу ошибку 406.

Раньше я использовал ODataConventionModelBuilder для установки EntitySets, и это работало нормально.

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Detail>("Details");
    builder.EntitySet<Item>("Items");
    builder.EntitySet<Order>("Orders");
    builder.EntitySet<Customer>("Customers");

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

Я надеюсь, что вопрос имеет смысл.

* РЕДАКТИРОВАТЬ: я добавил список GCSodContext и фрагмент из контроллера Customers.

namespace GCSbz3.Models
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;

    public partial class GCSodContext : DbContext
    {
        public GCSodContext()
            : base("name=GCSodContext")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public virtual DbSet<Customer> Customers { get; set; }
        public virtual DbSet<Detail> Details { get; set; }
        public virtual DbSet<Item> Items { get; set; }
        public virtual DbSet<Order> Orders { get; set; }
    }
}

а вот контроллер клиентов

...
using System.Web.Http;
using System.Web.Http.ModelBinding;
using System.Web.Http.OData;
using System.Web.Http.OData.Routing;
using GCSbz3.Models;

namespace GCSbz3.Controllers
{
    public class CustomersController : ODataController
    {
        private GCSodContext db = new GCSodContext();

        // GET odata/Customers
        [Queryable]
        public IQueryable<Customer> GetCustomers()
        {
            return db.Customers;
        }
...

Вот класс клиента.

namespace GCSbz3.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Customer
    {
        public Customer()
        {
            this.Orders = new HashSet<Order>();
        }

        public int CustID { get; set; }
        public string FName { get; set; }
        public string LName { get; set; }
        public string Phone { get; set; }

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

person Chi Row    schedule 04.04.2014    source источник
comment
Когда вы пытаетесь /odata/Customers, какое сообщение об ошибке вы получаете?   -  person coni2k    schedule 05.04.2014


Ответы (1)


Проверьте свое имя ODataController, оно должно быть выровнено с именем EntitySet в вашем edmx.

Если имя набора — CustomerSet, контроллер должен быть CustomerSetController с общедоступным методом GetCustomerSet.

Например, это работает;

TestDbContext.cs

public partial class TestDbContext : DbContext
{
    public TestDbContext()
        : base("name=TestDbContext")
    {}

    public virtual DbSet<A1> A1Set { get; set; }
}

A1SetController.cs

public class A1SetController : ODataController
{
    private TestDbContext db = new TestDbContext();

    // GET odata/A1Set
    [Queryable]
    public IQueryable<A1> GetA1Set()
    {
        return db.A1Set;
    }
}

И настройка маршрутизации в WebApiConfig.cs.

// OData routes
config.Routes.MapODataRoute(
    routeName: "odata",
    routePrefix: "odata",
    model: EdmBuilder.GetEdm<TestDbContext>(),
    batchHandler: new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));

И, наконец, пространства имен edmx и фактической модели (класса) должны быть выровнены. Когда вы делаете запрос к $metadata, вы видите определенное пространство имен для вашей модели. Вы можете изменить его в Конструкторе моделей, щелкните правой кнопкой мыши пустую область, выберите Свойства. В окне свойств вы можете увидеть атрибут Namespace. В моем случае;

<Schema Namespace="Web">
    <EntityType Name="Customer">

И Customer.cs

namespace Web
{
    using System;
    using System.Collections.Generic;

    public partial class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}
person coni2k    schedule 04.04.2014
comment
Я получаю сообщение об ошибке 406, когда пытаюсь ввести «/odata/Customers». '/odata' и '/odata/$metadata' оба работают, но не являются маршрутом к контроллерам - person Chi Row; 05.04.2014
comment
Мой контекст и контроллеры выглядят как ваш образец. Единственное, что, как мне кажется, может вызвать проблему, это то, что мое контекстное имя не заканчивается словом «Контекст». Позвольте мне попробовать изменить это и посмотреть, будет ли это иметь значение. - person Chi Row; 05.04.2014
comment
Все еще получаю ошибку 406 после изменения имени. Я добавил фрагменты к своему исходному вопросу. Почему при использовании ODataConventionModelBuilder для построения модели мне нужно добавить «.EntitySet» в модель для маршрутизации, но новый EdmBuilder не требует этого? - person Chi Row; 05.04.2014
comment
@ChiRow Вероятно, 406 происходит из-за разницы в пространстве имен. Я обновил свой ответ, пожалуйста, проверьте последнюю часть. Также проверьте конфигурацию своего маршрута, вы больше не используете ODataConventionModelBuilder, верно? Также вы видите метаданные, когда делаете запрос к /odata/$metadata? - person coni2k; 05.04.2014
comment
@ChiRow EdmBuilder напрямую читает из вашего файла edmx, он определяет все эти сущности, наборы и их отношения. Так что нет необходимости определять снова. Мне кажется, по умолчанию в шаблоне OData есть только отдельные сущности. Я предполагаю, что они улучшат это позже. - person coni2k; 05.04.2014
comment
1)Только новый шаблон. Нет шаблона OData по умолчанию. 2) $metadata показывает пространство имен GCSbz3, которое соответствует пространству имен edmx. 3) Контроллеры находились в пространстве имен GCSbz3.Controllers. Я изменил его только на GCSbz3, и все равно не повезло. Просто получаю ошибку 406. - person Chi Row; 05.04.2014
comment
edmx context entitycontainer показывает, что наборы сущностей находятся там. Однако разве этот контейнер не должен принадлежать модели или, по крайней мере, у модели также должна быть копия этого контейнера? - person Chi Row; 05.04.2014
comment
@ChiRow Класс клиента находится в пространстве имен GCSbz3 или GCSbz3.Models? Это пространство имен и edmx необходимо согласовать. - person coni2k; 05.04.2014
comment
@ChiRow Не могли бы вы добавить класс Customer к своему вопросу? - person coni2k; 06.04.2014
comment
Класс Customer находится в пространстве имен GCSbz3.Models. Позвольте мне изменить это и посмотреть, работает ли это. - person Chi Row; 06.04.2014
comment
Ура! это исправило. БОЛЬШОЕ СПАСИБО!!! Проблема заключалась в том, что код, сгенерированный сначала БД, всегда прикреплял «.Models» к концу пространства имен. Я избавился от них и теперь все работает. - person Chi Row; 06.04.2014
comment
@ChiRow Это правда, обычно пространства имен по умолчанию для edmx и сгенерированные модели отличаются. Что ж, рад, что ваша проблема решена. - person coni2k; 06.04.2014
comment
Хорошая темка, мне поможет. В любом случае, кто-нибудь знает, возможно ли не использовать одно и то же пространство имен для контекста БД и моделей? - person Dragouf; 28.06.2014
comment
@Dragouf Насколько я знаю, это невозможно - person coni2k; 30.06.2014