我正在实现一个自定义数据提供程序,我已经知道它可以返回数据并且可以进行过滤,但是在使关系正常工作方面遇到了一些麻烦。
当查询元数据时,关系看起来正确,当查询表时,会出现相关的属性链接,但是当尝试访问ResourceReference属性时,出现以下异常:
Object reference not set to an instance of an object.
System.NullReferenceException
stacktrace at System.Data.Services.Providers.DataServiceProviderWrapper.GetResourceAssociationSet(ResourceSetWrapper resourceSet, ResourceType resourceType, ResourceProperty resourceProperty)
at System.Data.Services.Providers.DataServiceProviderWrapper.GetContainer(ResourceSetWrapper sourceContainer, ResourceType sourceResourceType, ResourceProperty navigationProperty)
at System.Data.Services.Providers.DataServiceProviderWrapper.GetResourceProperties(ResourceSetWrapper resourceSet, ResourceType resourceType)
at System.Data.Services.Serializers.SyndicationSerializer.WriteObjectProperties(IExpandedResult expanded, Object customObject, ResourceType resourceType, Uri absoluteUri, String relativeUri, SyndicationItem item, DictionaryContent content, EpmSourcePathSegment currentSourceRoot)
at System.Data.Services.Serializers.SyndicationSerializer.WriteEntryElement(IExpandedResult expanded, Object element, ResourceType expectedType, Uri absoluteUri, String relativeUri, SyndicationItem target)
at System.Data.Services.Serializers.SyndicationSerializer.WriteTopLevelElement(IExpandedResult expanded, Object element)
at System.Data.Services.Serializers.Serializer.WriteRequest(IEnumerator queryResults, Boolean hasMoved)
at System.Data.Services.ResponseBodyWriter.Write(Stream stream)
这是我如何创建关系的示例:
var sourceReference = new ResourceProperty(
relatedType.ResourceTypeName,
ResourcePropertyKind.ResourceReference,
relatedType.ResourceType);
sourceReference.CanReflectOnInstanceTypeProperty = false;
compoundType.ResourceType.AddProperty(sourceReference);
var destinationReference = new ResourceProperty(
compoundType.ResourceSetName,
ResourcePropertyKind.ResourceSetReference,
compoundType.ResourceType);
destinationReference.CanReflectOnInstanceTypeProperty = false;
source.ResourceType.AddProperty(destinationReference);
var sourceAssociation = new ResourceAssociationSet(
"source",
new ResourceAssociationSetEnd(compoundType.ResourceSet, compoundType.ResourceType, sourceReference),
new ResourceAssociationSetEnd(relatedType.ResourceSet, relatedType.ResourceType, null));
var destinationAssociation = new ResourceAssociationSet(
"destination",
new ResourceAssociationSetEnd(relatedType.ResourceSet, relatedType.ResourceType, destinationReference),
new ResourceAssociationSetEnd(compoundType.ResourceSet, compoundType.ResourceType, null));
通过查看OData网站上的示例代码,我认为我已经正确完成了所有操作,并且无法确定我的错误。有任何想法吗?或调试自定义WCF数据服务的提示?
更新:
这是在null异常之前发生的事情。
有一个资源集与项目有关系的项圈,所以我执行以下查询:
blah.svc/Collars(1)/项目
我在IDataServiceMetadataProvider中对GetResourceAssociationSet的重写使用参数ResourceSet = Collars,ResourceType = Collar,Property = Project调用,并且返回上面指定的关联集。
然后使用ResourceSet = Projects,ResourceType = Collar,Property = Project再次调用GetResourceAssociationSet,然后返回相同的关联集。
然后在System.Data.Services.Providers.GetResourceAssociationSetEnd中,传入的变量为resourceSet = Projects,resourceType = Collar,resourceProperty = Project,此函数返回null。
这使得System.Data.Services.Providers.DataServiceProviderWrapper.GetResourceAssociationSet中的thisEnd等于null。
然后,使用相同的变量调用GetRelatedResourceAssociationSetEnd,并且还返回null。
所以它随即崩溃
ResourceSetWrapper relatedSet = this.ValidateResourceSet(relatedEnd.ResourceSet);
因为relatedEnd为null。
最佳答案
好吧,在调试中,我注意到上一次在发生错误之前调用GetResourceAssociationSet是因为resourceSet和resourceType参数具有不同的值(对于派生类型)。
所以,我看了看,发现了这个
WCF data services (OData), query with inheritance limitation?
...并且瞧瞧这个无用的空引用异常(至少在我的情况下)是由同一问题引起的。我删除了令人反感的属性(然后将其移至基本资源集,即使实际上实际上不存在该属性集)也已解决。
有趣的旁注(以防对原始海报有所帮助):ResourceType.Properties包括“基本类型”中的属性。必须更改一些代码以改为使用PropertiesDeclaredOnThisType ...