[英]Why do I keep getting “ Properties whose types are collection of primitives or complex types are not supported.”?
我有一个定义如下的实体(由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数据服务公开此类,则会出现以下异常:
服务器在处理请求时遇到错误。 异常消息是'DomainObjects.EntityFrameworkModel.Gac类型的'TransactionList'属性不是有效的属性。 不支持其类型为原始类型或复杂类型集合的属性。 有关更多详细信息,请参见服务器日志。 异常堆栈跟踪为:
在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
System.Data.Services.Providers.ReflectionServiceProvider.PopulateMetadata(IDictionary2 knownTypes, IDictionary
2 childTypes,IDictionary2 entitySets) at System.Data.Services.Providers.BaseServiceProvider.PopulateMetadata() at System.Data.Services.DataService
2个childTypes,队列1 unvisitedTypes, IEnumerable
1个EntitySets2 entitySets) at System.Data.Services.Providers.BaseServiceProvider.PopulateMetadata() at System.Data.Services.DataService
1.CreateProvider()在System.Data.Services.DataService1.EnsureProviderAndConfigForRequest() at System.Data.Services.DataService
1.HandleRequest()在System.Data.Services.DataService`1。 System.ServiceModel.Dispatcher.S上SyncInvoke的ProcessRequestForMessage(Stream messageBody)ProcessRequestForMessage(Object,Object [],Object []) yncMethodInvoker.Invoke(在System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&rpc)在System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&rpc)在System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&rpc) System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&rpc)位于System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31path.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc&rpc)在System.ServiceModel.Run rpc)位于System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&rpc)位于System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&rpc)位于System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&Dispatcher) .MessageRpc.Process(布尔值isOperationContextSet)
Gac类包含如下定义的属性TransactionList:
public IQueryable<TransactionList> TransactionList
{
get { return _myContext.TransactionList.AsNoTracking(); }
}
为什么会出现此异常? 我在WCF服务器日志中看不到任何有用的信息。 对您有用的信息可能是该实体表示数据库视图。 我已经公开了一个类似的实体,其中包含相同类型的属性int,DateTime,string),并且该实体正在运行。
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上运行,那么我认为CreateDataSource内部的逻辑就足够了。
我认为WCF尝试序列化TransactionList属性。 您可以放置告诉WCF跳过属性的属性(类似于[IgnoreDataMember]),或将该属性转换为方法GetTransationList()。
我认为您不能将泛型公开给Web服务。 通常,我不会将ADO.net数据实体公开给Web服务。 您应该从Web服务代码中提取数据类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.