Почему я продолжаю получать «Свойства, типы которых являются коллекцией примитивов или сложные типы не поддерживаются»? - PullRequest
1 голос
/ 21 ноября 2011

У меня есть объект, определенный следующим образом (код, сгенерированный генератором POCO VS2010):

public partial class TransactionList
    {
        public int tlRecordId { get; set; }
        public Nullable<int> tlTracer { get; set; }
        public Nullable<int> tlRecordType { get; set; }
        public Nullable<int> tlPayType { get; set; }
        public Nullable<int> pdmNumber { get; set; }
        public string pdmName { get; set; }
        public string zoneName { get; set; }
        public string groupName { get; set; }
        public Nullable<int> serviceCarNumber { get; set; }
        public Nullable<int> moneyCarNumber { get; set; }
        public Nullable<System.DateTime> tlPayDateTime { get; set; }
        public Nullable<System.DateTime> tlExpDateTime { get; set; }
        public Nullable<int> senderPdmNumber { get; set; }
        public Nullable<int> tlAmount { get; set; }
        public Nullable<int> tlTicketNo { get; set; }
    }

, и существует второй частичный класс для этого класса (написанный вручную), который содержит атрибут Key.

[DataServiceKey("tlRecordId")]
public partial class TransactionList
{ }

Таким образом, в этом классе не определены коллекции сложных типов / примитивов.Если я предоставляю этот класс с помощью служб данных WCF, я получаю следующее исключение:

Сервер обнаружил ошибку при обработке запроса.Сообщение об исключении: «Свойство« TransactionList »типа« DomainObjects.EntityFrameworkModel.Gac »не является допустимым свойством.Свойства, типы которых являются коллекцией примитивов или сложных типов, не поддерживаются. '.Смотрите журналы сервера для более подробной информации.Трассировка стека исключений:

в System.Data.Services.Providers.ReflectionServiceProvider.BuildTypeProperties (ResourceType parentResourceType, IDictionary 2 knownTypes, IDictionary 2 childTypes, очередь 1 unvisitedTypes, IEnumerable 1 entitySets) в System.Data.Services.Providers..ReflectionServiceProvider.PopulateMetadataForTypes (IDictionary 2 knownTypes, IDictionary 2 childTypes, Очередь 1 unvisitedTypes, IEnumerable 1 entitySets) в System.Data.Services.Providers.ReflectionServiceProvider.PopulateMetadata (IDictionary 2 knownTypes, IDictionary 2 childTypes, IDC) 101Pate at 101Pate в 1017.Data.Services.DataService 1.EnsureProviderAndConfigForRequest() at System.Data.Services.DataService 1.HandleRequest () в System.Data.Services.DataService`1.ProcessRequestForMessage (Stream messageBody) в SyncInvokeProcessRequestForMessage (Object, Object [], Object []) в System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke (экземпляр объекта, входные данные Object [], Object [] и выходные данные) в System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin (MessageRpc & rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcPessRessage (Message) ProcMRessage.PecMна System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41 (MessageRpc & RPC) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4 (MessageRpc & RPC) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31 (MessageRpc & Rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3 (MessageRpc & rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2 (MessageRpc & rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Process1..ServiceModel.Dispatcher.MessageRpc.Process (Boolean isOperationContextSet)

Класс Gac содержит свойство TransactionList, определенное следующим образом:

public IQueryable<TransactionList> TransactionList
{
  get { return _myContext.TransactionList.AsNoTracking(); }
}

Почему я получаю это исключение?Я не вижу никакой полезной информации в журнале сервера WCF.Полезной информацией для вас может быть то, что этот объект представляет представление базы данных.Я уже выставляю похожую сущность, которая содержит такие же типы свойств, как int, DateTime, string), и она работает.

** ОБНОВЛЕНИЕ ** Добавлено определение службы данных (я исключил методы IDisposable):

public class DummyService : DataService<CustomContext>
{
  protected override CustomContext CreateDataSource()
  {
     //I need a single endpoint exposing data from more databases. Here I pass
     //the data needed for the creation of connection strings
     var dataSource = new CustomContext(new int []{1,2,3});
     return dataSource;
   }
}

///This class represents my single endpoint exposing data from various databases.
///Every database has the same DB schema.
public class CustomContext: IDisposable
{
  private static IList<Gac> _gacList;

  //Here I construct the list of accessible data sources - databases. This list
  // can vary
  public CustomContext(IEnumerable<AreaCodes> areaCodes)
  {
    //This is the list of various databases exposed via OData
    _gacList = new List<Gac>();

    foreach (AreaCodes ac in areaCodes)
    {
      //When calling the constructor of Gac, the DbContext gets created.
      _gacList.Add(new Gac(ac.Id));
    }
  }

  //the entity which will be exposed
  public IQueryable<Gac> Gac
  {
      get { return _gacList != null ? _gacList.AsQueryable() : null; }
  }
}

///This class represents a single data source - a database. 
//All databases are exposed over single endpoint
[DataServiceKey("GacId")]
public class Gac: IDisposable
{
    private MyContext _myContext;
    private int _gacId;

  public Gac(int areaCode)
  {
    //Here I finally create my context
    _myContext= new MyContext("...Connection String Generated based on areaCode");
    _myContext.Configuration.ProxyCreationEnabled = false;
    _myContext.Configuration.LazyLoadingEnabled = false;

    _gacId = areaCode;
  }  

  //This property uniquely identifies a GAC object. It is an entity key.
  public int GacId
  {
    get { return _gacId; }
  }

  //Expose an entity from the EF layer
  public IQueryable<TransactionList> TransactionList
  {
    get { return _myContext.TransactionList.AsNoTracking(); }
  }

  //...Other about 25 IQueryable properties
}

//generated Entity Framework Conceptual Layer
public partial class MyContext: DbContext
{
  //This entity represents my database view which I want to access to
  public DbSet<TransactionList> TransactionList { get; set; }
  //...Other about 25 generic DbSet properties
}

Ответы [ 3 ]

2 голосов
/ 22 ноября 2011

Предоставляете ли вы свойство типа IQueryable в вашем классе Context? Если нет, то это проблема. Чтобы класс был признан как сущность, он должен быть представлен в наборе сущностей (иметь свойство в классе Context) и иметь ключ (либо эвристика, либо атрибут DataServiceKey).

Также обратите внимание, что, похоже, вы определяете службу на основе отражений в хранилище данных на основе EF. Это будет иметь проблемы с более сложными запросами. WCF DS генерирует несколько иные деревья выражений для поставщика отражений и поставщика EF (необходимо из-за пространства допустимых выражений, поддерживаемых этими). Деревья, созданные для поставщика отражения, не всегда совместимы с EF (и наоборот).

Если бы вы могли поделиться большим количеством своего класса Context, возможно, есть способ сделать это без принудительного использования поставщика отражений. Я понимаю, что вы предоставляете несколько БД поверх службы, но как вы запускаете, с какой БД будет выполняться входящий запрос? Если это можно определить, взглянув на один запрос, и каждый запрос может выполняться только на одной БД, то я думаю, что достаточно немного логики внутри CreateDataSource.

0 голосов
/ 21 ноября 2011

Я думаю, что WCF пытается сериализовать свойство TransactionList.Вы можете поместить атрибут, который сообщает WCF, чтобы пропустить свойство (что-то вроде [IgnoreDataMember]) или преобразовать это свойство в метод GetTransationList ().

0 голосов
/ 21 ноября 2011

Не думаю, что вы можете выставлять дженерики веб-сервисам.Как правило, я не предоставляю сущности данных ADO.net веб-сервису.Вы должны абстрагировать свои классы данных от кода вашего веб-сервиса.

...