Hey all, I have two functions in a SL project (VS2010) that do almost exactly the same thing, yet one throws an error and the other does not. It seems to be related to the projections, but I am unsure about the best way to resolve.
The function that works is...
public void LoadAllChunksExpandAll(DataHelperReturnHandler handler, string orderby)
{
DataServiceCollection<CmsChunk> data = null;
DataServiceQuery<CmsChunk> theQuery = _dataservice
.CmsChunks
.Expand("CmsItemState")
.AddQueryOption("$orderby", orderby);
theQuery.BeginExecute(
delegate(IAsyncResult asyncResult)
{
_callback_dispatcher.BeginInvoke(
() =>
{
try
{
DataServiceQuery<CmsChunk> query = asyncResult.AsyncState as DataServiceQuery<CmsChunk>;
if (query != null)
{
//create a tracked DataServiceCollection from the result of the asynchronous query.
QueryOperationResponse<CmsChunk> queryResponse =
query.EndExecute(asyncResult) as QueryOperationResponse<CmsChunk>;
data = new DataServiceCollection<CmsChunk>(queryResponse);
handler(data);
}
}
catch
{
handler(data);
}
}
);
},
theQuery
);
}
This compiles and runs as expected. A very, very similar function (shown below) fails...
public void LoadAllPagesExpandAll(DataHelperReturnHandler handler, string orderby)
{
DataServiceCollection<CmsPage> data = null;
DataServiceQuery<CmsPage> theQuery = _dataservice
.CmsPages
.Expand("CmsChildPages")
.Expand("CmsParentPage")
.Expand("CmsItemState")
.AddQueryOption("$orderby", orderby);
theQuery.BeginExecute(
delegate(IAsyncResult asyncResult)
{
_callback_dispatcher.BeginInvoke(
() =>
{
try
{
DataServiceQuery<CmsPage> query = asyncResult.AsyncState as DataServiceQuery<CmsPage>;
if (query != null)
{
//create a tracked DataServiceCollection from the result of the asynchronous query.
QueryOperationResponse<CmsPage> queryResponse = query.EndExecute(asyncResult) as QueryOperationResponse<CmsPage>;
data = new DataServiceCollection<CmsPage>(queryResponse);
handler(data);
}
}
catch
{
handler(data);
}
}
);
},
theQuery
);
}
Clearly the issue is the Expand projections that involve a self referencing relationship (pages can contain other pages). This is under SL4 or SL3 using ADONETDataServices SL3 Update CTP3.
I am open to any work around or pointers to goo information, a Google search for the error results in two hits, neither particularly helpful that I can decipher.
The short error is "An item could not be added to the collection. When items in a DataServiceCollection are tracked by the DataServiceContext, new items cannot be added before items have been loaded into the collection."
The full error is...
System.Reflection.TargetInvocationException
was caught Message=Exception has
been thrown by the target of an
invocation. StackTrace:
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo
method, Object target, Object[]
arguments, SignatureStruct& sig,
MethodAttributes methodAttributes,
RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object
obj, BindingFlags invokeAttr, Binder
binder, Object[] parameters,
CultureInfo culture, Boolean
skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object
obj, BindingFlags invokeAttr, Binder
binder, Object[] parameters,
CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object
obj, Object[] parameters)
at System.Data.Services.Client.ClientType.ClientProperty.SetValue(Object
instance, Object value, String
propertyName, Boolean allowAdd)
at System.Data.Services.Client.AtomMaterializer.ApplyItemsToCollection(AtomEntry
entry, ClientProperty property,
IEnumerable items, Uri nextLink,
ProjectionPlan continuationPlan)
at System.Data.Services.Client.AtomMaterializer.ApplyFeedToCollection(AtomEntry
entry, ClientProperty property,
AtomFeed feed, Boolean includeLinks)
at System.Data.Services.Client.AtomMaterializer.MaterializeResolvedEntry(AtomEntry
entry, Boolean includeLinks)
at System.Data.Services.Client.AtomMaterializer.Materialize(AtomEntry
entry, Type expectedEntryType, Boolean
includeLinks)
at System.Data.Services.Client.AtomMaterializer.DirectMaterializePlan(AtomMaterializer
materializer, AtomEntry entry, Type
expectedEntryType)
at System.Data.Services.Client.AtomMaterializerInvoker.DirectMaterializePlan(Object
materializer, Object entry, Type
expectedEntryType)
at System.Data.Services.Client.ProjectionPlan.Run(AtomMaterializer
materializer, AtomEntry entry, Type
expectedType)
at System.Data.Services.Client.AtomMaterializer.Read()
at System.Data.Services.Client.MaterializeAtom.MoveNextInternal()
at System.Data.Services.Client.MaterializeAtom.MoveNext()
at System.Linq.Enumerable.d_b11.MoveNext()
at System.Data.Services.Client.DataServiceCollection1.InternalLoadCollection(IEnumerable1 items)
at System.Data.Services.Client.DataServiceCollection1.StartTracking(DataServiceContext
context, IEnumerable1 items, String
entitySet, Func2 entityChanged,
Func2 collectionChanged)
at System.Data.Services.Client.DataServiceCollection1..ctor(DataServiceContext
context, IEnumerable1 items,
TrackingMode trackingMode, String
entitySetName, Func2
entityChangedCallback, Func2
collectionChangedCallback)
at System.Data.Services.Client.DataServiceCollection1..ctor(IEnumerable1
items)
at Phinli.Dashboard.Silverlight.Helpers.DataHelper.<>c__DisplayClass44.<>c__DisplayClass46.<LoadAllPagesExpandAll>b__43()
InnerException:
System.InvalidOperationException
Message=An item could not be added to the collection. When items in
a DataServiceCollection are tracked by
the DataServiceContext, new items
cannot be added before items have been
loaded into the collection.
StackTrace:
at System.Data.Services.Client.DataServiceCollection1.InsertItem(Int32
index, T item)
at System.Collections.ObjectModel.Collection`1.Add(T
item)
InnerException:
Thanks for any help!