为什么我总是得到"不支持类型为原语或复杂类型集合的属性."

本文关键字:quot 类型 原语 复杂 集合 属性 为什么 不支持 | 更新日期: 2023-09-27 18:15:29

我有一个定义如下的实体(由VS2010 POCO生成器生成的代码):

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 (ResourceTypeparentResourceType, IDictionary 2 knownTypes, IDictionarychildTypes, Queue 1 unvisitedTypes, IEnumerable 1 entitySets) atSystem.Data.Services.Providers.ReflectionServiceProvider。PopulateMetadataForTypes(dicictionary 2 knownTypes, IDictionary 2 childTypes, Queue 1 unvisitedTypes, IEnumerable 1 entitySets) atSystem.Data.Services.Providers.ReflectionServiceProvider。PopulateMetadata(IDictionary 2 knownTypes, IDictionary 2 childTypes, IDictionary 2 entitySets) at System.Data.Services.Providers.BaseServiceProvider.PopulateMetadata() at System.Data.Services.DataService 1.CreateProvider() atSystem.Data.Services.DataService 1.EnsureProviderAndConfigForRequest() at System.Data.Services.DataService . handlerrequest (System.Data.Services.DataService 1. processrequestformessage(流在SyncInvokeProcessRequestForMessage(对象,对象[],对象[])System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(对象实例,对象[]输入,对象[]&输出)System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin (MessageRpc&rpc)System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5 (MessageRpc&rpc)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.ProcessMessage11 (MessageRpc&rpc)System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1 (MessageRpc&System.ServiceModel.Dispatcher.MessageRpc.Process(布尔值isOperationContextSet)

类Gac包含如下定义的TransactionList属性:

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

为什么我得到这个异常?我在WCF服务器日志中没有看到任何有用的信息。一个有用的信息是,这个实体表示一个数据库视图。我已经暴露了一个类似的实体,它包含相同类型的属性(int, DateTime, string),它正在工作。

** UPDATE **添加了数据服务定义(我省略了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
}

为什么我总是得到"不支持类型为原语或复杂类型集合的属性."

你是否在你的Context类上公开了一个IQueryable类型的属性?如果不是,那就是问题所在。为了使一个类被识别为一个实体,它必须在实体集中公开(在Context类上有一个属性),并且它必须有一个键(启发式或DataServiceKey属性)。

还要注意,您似乎在基于EF的数据存储上定义了基于反射的服务。这将在处理更复杂的查询时产生问题。WCF DS为反射提供程序和EF提供程序生成的表达式树有些不同(这是必要的,因为它们支持的有效表达式空间很大)。为反射提供程序生成的树并不总是与EF兼容(反之亦然)。

如果你可以共享更多的Context类,也许有一种方法可以做到这一点,而不强制使用反射提供者。我知道您在服务上公开了几个DB,但是您如何运行哪个DB来运行传入请求呢?如果它可以通过单独查看请求来确定,并且每个请求只能在单个DB上运行,那么我认为只需在CreateDataSource中添加一点逻辑就足够了。

我认为WCF试图序列化TransactionList属性。你可以把属性告诉WCF跳过属性(类似[IgnoreDataMember])或转换该属性方法GetTransationList()。

我不认为你可以向web服务公开泛型。作为一般规则,我不会向web服务公开ADO.net数据实体。您应该从web服务代码中抽象出您的数据类。

相关文章: