为什么我总是得到"不支持类型为原语或复杂类型集合的属性."
本文关键字: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, IDictionary
childTypes, Queue1 unvisitedTypes, IEnumerable
1 entitySets) atSystem.Data.Services.Providers.ReflectionServiceProvider。PopulateMetadataForTypes(dicictionary2 knownTypes, IDictionary
2 childTypes, Queue1 unvisitedTypes, IEnumerable
1 entitySets) atSystem.Data.Services.Providers.ReflectionServiceProvider。PopulateMetadata(IDictionary2 knownTypes, IDictionary
2 childTypes, IDictionary2 entitySets) at System.Data.Services.Providers.BaseServiceProvider.PopulateMetadata() at System.Data.Services.DataService
1.CreateProvider() atSystem.Data.Services.DataService1.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服务代码中抽象出您的数据类。