SharePoint Online BCS OData External Content Can't Update, View or Delete - odata

Using Visual Studio 2013, I created an Entity Model over an existing database. Each table has a GUID for it's primary key. I created an MVC Web API project with related OData Bindings and Controllers.
Here is how I create the OData Binding;
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<HRPosition>("HRPositions").EntityType.HasKey(p=>p.HTPositionGuid);
Here is a sample controller for the HRPositions Entity.
public class HRPositionsController : ODataController
{
private EFSEntities db = new EFSEntities();
// GET: odata/HRPositions
[EnableQuery]
public IQueryable<HRPosition> GetHRPositions()
{
return db.HRPositions;
}
// GET: odata/HRPositions(5)
[EnableQuery]
public SingleResult<HRPosition> GetHRPosition([FromODataUri] Guid key)
{
return SingleResult.Create(db.HRPositions.Where(hRPosition => hRPosition.HTPositionGuid == key));
}
// PUT: odata/HRPositions(5)
public async Task<IHttpActionResult> Put([FromODataUri] Guid key, Delta<HRPosition> patch)
{
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
HRPosition hRPosition = await db.HRPositions.FindAsync(key);
if (hRPosition == null)
{
return NotFound();
}
patch.Put(hRPosition);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!HRPositionExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(hRPosition);
}
// POST: odata/HRPositions
public async Task<IHttpActionResult> Post(HRPosition hRPosition)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.HRPositions.Add(hRPosition);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (HRPositionExists(hRPosition.HTPositionGuid))
{
return Conflict();
}
else
{
throw;
}
}
return Created(hRPosition);
}
// PATCH: odata/HRPositions(5)
[AcceptVerbs("PATCH", "MERGE")]
public async Task<IHttpActionResult> Patch([FromODataUri] Guid key, Delta<HRPosition> patch)
{
Validate(patch.GetEntity());
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
HRPosition hRPosition = await db.HRPositions.FindAsync(key);
if (hRPosition == null)
{
return NotFound();
}
patch.Patch(hRPosition);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!HRPositionExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(hRPosition);
}
// DELETE: odata/HRPositions(5)
public async Task<IHttpActionResult> Delete([FromODataUri] Guid key)
{
HRPosition hRPosition = await db.HRPositions.FindAsync(key);
if (hRPosition == null)
{
return NotFound();
}
db.HRPositions.Remove(hRPosition);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool HRPositionExists(Guid key)
{
return db.HRPositions.Count(e => e.HTPositionGuid == key) > 0;
}
}
Once the OData Service is deployed and using Fiddler I am able to query the Service endpoints and retrieve the full list of data as well as single entity data.
I then created a SharePoint App in which I create an External Content Type by referencing the OData service. This creates the ECT Model definitions for each endpoint.
Here is the ECT for HRPositions;
<?xml version="1.0" encoding="utf-16"?>
<Model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="EFSData" xmlns="http://schemas.microsoft.com/windows/2007/BusinessDataCatalog">
<LobSystems>
<LobSystem Name="EFSODATA" Type="OData">
<Properties>
<Property Name="ODataServiceMetadataUrl" Type="System.String">https://efsodataapi.azurewebsites.net/OData/$metadata</Property>
<Property Name="ODataServiceMetadataAuthenticationMode" Type="System.String">PassThrough</Property>
<Property Name="ODataServicesVersion" Type="System.String">2.0</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<LobSystemInstances>
<LobSystemInstance Name="EFSODATA">
<Properties>
<Property Name="ODataServiceUrl" Type="System.String">https://efsodataapi.azurewebsites.net/OData</Property>
<Property Name="ODataServiceAuthenticationMode" Type="System.String">PassThrough</Property>
<Property Name="ODataFormat" Type="System.String">application/atom+xml</Property>
<Property Name="HttpHeaderSetAcceptLanguage" Type="System.Boolean">true</Property>
</Properties>
</LobSystemInstance>
</LobSystemInstances>
<Entities>
<Entity Name="HRPositions" DefaultDisplayName="HRPositions" Namespace="EFSData" Version="1.0.0.0" EstimatedInstanceCount="2000">
<Properties>
<Property Name="ExcludeFromOfflineClientForList" Type="System.String">False</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<Identifiers>
<Identifier Name="HTPositionGuid" TypeName="System.Guid" />
</Identifiers>
<Methods>
<Method Name="CreateHRPosition" DefaultDisplayName="Create HRPosition" IsStatic="false">
<Properties>
<Property Name="ODataEntityUrl" Type="System.String">/HRPositions</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<Parameters>
<Parameter Name="#HTPositionGuid" Direction="In">
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" CreatorField="true" />
</Parameter>
<Parameter Name="#PosistionCode" Direction="In">
<TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" CreatorField="true" />
</Parameter>
<Parameter Name="#PositionName" Direction="In">
<TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" CreatorField="true" />
</Parameter>
<Parameter Name="#Description" Direction="In">
<TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" CreatorField="true" />
</Parameter>
<Parameter Name="#CreateHRPosition" Direction="Return">
<TypeDescriptor Name="CreateHRPosition" DefaultDisplayName="CreateHRPosition" TypeName="Microsoft.BusinessData.Runtime.DynamicType">
<TypeDescriptors>
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" ReadOnly="true" />
<TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" />
<TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" />
<TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" />
</TypeDescriptors>
</TypeDescriptor>
</Parameter>
</Parameters>
<MethodInstances>
<MethodInstance Name="CreateHRPosition" Type="Creator" ReturnParameterName="#CreateHRPosition" ReturnTypeDescriptorPath="CreateHRPosition">
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
</MethodInstance>
</MethodInstances>
</Method>
<Method Name="ReadSpecificHRPosition" DefaultDisplayName="Read Specific HRPosition" IsStatic="false">
<Properties>
<Property Name="ODataEntityUrl" Type="System.String">/HRPositions(HTPositionGuid=guid'#HTPositionGuid')</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<Parameters>
<Parameter Name="#HTPositionGuid" Direction="In">
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" />
</Parameter>
<Parameter Name="#HRPosition" Direction="Return">
<TypeDescriptor Name="HRPosition" DefaultDisplayName="HRPosition" TypeName="Microsoft.BusinessData.Runtime.DynamicType">
<TypeDescriptors>
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" ReadOnly="true" />
<TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" />
<TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" />
<TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" />
</TypeDescriptors>
</TypeDescriptor>
</Parameter>
</Parameters>
<MethodInstances>
<MethodInstance Name="ReadSpecificHRPosition" Type="SpecificFinder" Default="true" ReturnParameterName="#HRPosition" ReturnTypeDescriptorPath="HRPosition">
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
</MethodInstance>
</MethodInstances>
</Method>
<Method Name="ReadAllHRPosition" DefaultDisplayName="Read All HRPosition" IsStatic="false">
<Properties>
<Property Name="ODataEntityUrl" Type="System.String">/HRPositions?$top=#LimitHRPositionss</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<FilterDescriptors>
<FilterDescriptor Name="LimitFilter" DefaultDisplayName="LimitFilter" Type="Limit" />
</FilterDescriptors>
<Parameters>
<Parameter Name="#LimitHRPositionss" Direction="In">
<TypeDescriptor Name="LimitHRPositionss" DefaultDisplayName="LimitHRPositionss" TypeName="System.Int32" AssociatedFilter="LimitFilter">
<Properties>
<Property Name="LogicalOperatorWithPrevious" Type="System.String">None</Property>
<Property Name="Order" Type="System.String">0</Property>
</Properties>
<DefaultValues>
<DefaultValue MethodInstanceName="ReadAllHRPosition" Type="System.Int32">100</DefaultValue>
</DefaultValues>
</TypeDescriptor>
</Parameter>
<Parameter Name="#HRPositions" Direction="Return">
<TypeDescriptor Name="HRPositions" DefaultDisplayName="HRPositions" TypeName="Microsoft.BusinessData.Runtime.IDynamicTypeEnumerator" IsCollection="true">
<TypeDescriptors>
<TypeDescriptor Name="HRPosition" DefaultDisplayName="HRPosition" TypeName="Microsoft.BusinessData.Runtime.DynamicType">
<TypeDescriptors>
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" ReadOnly="true" />
<TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" />
<TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" />
<TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" />
</TypeDescriptors>
</TypeDescriptor>
</TypeDescriptors>
</TypeDescriptor>
</Parameter>
</Parameters>
<MethodInstances>
<MethodInstance Name="ReadAllHRPosition" Type="Finder" Default="true" ReturnParameterName="#HRPositions" ReturnTypeDescriptorPath="HRPositions">
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
</MethodInstance>
</MethodInstances>
</Method>
<Method Name="UpdateHRPosition" DefaultDisplayName="Update HRPosition" IsStatic="false">
<Properties>
<Property Name="ODataEntityUrl" Type="System.String">/HRPositions(HTPositionGuid=guid'#HTPositionGuid')</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<Parameters>
<Parameter Name="#HTPositionGuid" Direction="In">
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" UpdaterField="true" />
</Parameter>
<Parameter Name="#PosistionCode" Direction="In">
<TypeDescriptor Name="PosistionCode" DefaultDisplayName="PosistionCode" TypeName="System.String" UpdaterField="true" />
</Parameter>
<Parameter Name="#PositionName" Direction="In">
<TypeDescriptor Name="PositionName" DefaultDisplayName="PositionName" TypeName="System.String" UpdaterField="true" />
</Parameter>
<Parameter Name="#Description" Direction="In">
<TypeDescriptor Name="Description" DefaultDisplayName="Description" TypeName="System.String" UpdaterField="true" />
</Parameter>
</Parameters>
<MethodInstances>
<MethodInstance Name="UpdateHRPosition" Type="Updater">
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
</MethodInstance>
</MethodInstances>
</Method>
<Method Name="DeleteHRPosition" DefaultDisplayName="Delete HRPosition" IsStatic="false">
<Properties>
<Property Name="ODataEntityUrl" Type="System.String">/HRPositions(HTPositionGuid=guid'#HTPositionGuid')</Property>
</Properties>
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
<Parameters>
<Parameter Name="#HTPositionGuid" Direction="In">
<TypeDescriptor Name="HTPositionGuid" DefaultDisplayName="HTPositionGuid" TypeName="System.Guid" IdentifierName="HTPositionGuid" />
</Parameter>
</Parameters>
<MethodInstances>
<MethodInstance Name="DeleteHRPosition" Type="Deleter">
<AccessControlList>
<AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">
<Right BdcRight="Edit" />
<Right BdcRight="Execute" />
<Right BdcRight="SelectableInClients" />
<Right BdcRight="SetPermissions" />
</AccessControlEntry>
</AccessControlList>
</MethodInstance>
</MethodInstances>
</Method>
</Methods>
</Entity>
</Entities>
</LobSystem>
</LobSystems>
</Model>
I uploaded the ECT into SharePoint Online BCS and all looks fine;
From there I create an external list and reference the HRPositions ECT, which creates and SP List but is missing the primary key (which is the GUID).
This view shows the proper data;
I am able to add a new item to the list;
And it shows in the read all view;
But I can't edit, delete or view any list item as I get this error for each operation;
I attached to the OData Web Service and could see why the issue is occurring. Turns out the Auto-Generated External Control Types (ECT) within Visual Studio that were reflected off the OData Service have an issue in that for some reason it is formulating the request as /HRPositions(HTPositionGuid=guid'#HTPositionGuid');
It should really only be /HRPositions(guid'#HTPositionGuid');
Can anyone tell me why it's including the HTPositionGuid= within the Parameter list?
I can manually edit the code-generated ECT files for each entity but that seems silly.

Related

The function import is missing in the metadata of odata (odata created via CDS)

I want to create a function import in odata for use in sapui5 application. I create CDS view, add BOPF, create action SEND_MAIL, add annotation to odata. But function import tag is still missing in the metadata, i dont know why. And Exporting type in action inactive. Determination working, action not. What i do wrong?
СDS View:
#AbapCatalog.sqlViewName: 'ZGUT_FIORY_VW'
#AbapCatalog.compiler.compareFilter: true
#VDM.viewType: #COMPOSITE
#AbapCatalog.preserveKey: true
#AccessControl.authorizationCheck: #CHECK
#EndUserText.label: 'Test cds fiori list report'
// BOPF CRUD
#Metadata.allowExtensions: true
#ObjectModel:{
modelCategory: #BUSINESS_OBJECT,
compositionRoot: true,
transactionalProcessingEnabled: true,
createEnabled: true,
updateEnabled: true,
deleteEnabled: true,
writeActivePersistence: 'ZGUT_TEST_UI5',
semanticKey: ['id'],
representativeKey: 'id'
}
#OData:{
publish:true
}
#UI.headerInfo: {
typeName : 'Тестовое приложение fiori', // Заголовок списка
typeNamePlural: 'Тестовое приложение fiori' ,
title.value: 'Title', // Заголовок детальной страницы
description.value: 'bukrs_txt'
}
#Search.searchable: true
define view ZGUT_CDS_FIORY as select from zgut_test_ui5
association [1..1] to t001 as _bukrs on zgut_test_ui5.bukrs = _bukrs.bukrs
association [0..*] to ZGUT_CHART_AMOUNT as _chartamount on zgut_test_ui5.curr = _chartamount.Curr
association [1..1] to ZGUT_CHART_AMOUNT as _chartamount2 on zgut_test_ui5.id = _chartamount2.Ids
{
#UI.lineItem:[
{position: 30},
{ type: #FOR_ACTION, dataAction: 'BOPF:SEND_MAIL', position: 1, label: 'Send mail' }
]
#ObjectModel.mandatory: true
key id as Id,
// Another fields
}
BOPF:
Action:
Action class:
Metadata (i dont see here any function import, i dont know why) /sap/opu/odata/sap/ZGUT_CDS_FIORY_CDS/$metadata:
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" Version="1.0">
<edmx:Reference xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Uri="http://host:50000/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Vocabularies(TechnicalName='%2FIWBEP%2FVOC_COMMON',Version='0001',SAP__Origin='LOCAL')/$value">
<edmx:Include Namespace="com.sap.vocabularies.Common.v1" Alias="Common"/>
</edmx:Reference>
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="ZGUT_CDS_FIORY_CDS" xml:lang="ru" sap:schema-version="1">
<EntityType Name="ZGUT_CDS_FIORYType" sap:label="Test cds fiori list report" sap:content-version="1">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Send_mail_ac" Type="Edm.Boolean" sap:label="Dyn. Action Control" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
<Property Name="Id" Type="Edm.String" Nullable="false" MaxLength="6" sap:display-format="NonNegative" sap:label="Номер"/>
<Property Name="Descr" Type="Edm.String" sap:label="Описание"/>
<Property Name="target_amount" Type="Edm.String" MaxLength="6" sap:display-format="NonNegative" sap:label="Количество"/>
<Property Name="Title" Type="Edm.String" MaxLength="255" sap:label="Заголовок"/>
<Property Name="Bukrs" Type="Edm.String" MaxLength="4" sap:display-format="UpperCase" sap:label="БЕ"/>
<Property Name="bukrs_txt" Type="Edm.String" MaxLength="25" sap:label="Название фирмы" sap:creatable="false" sap:updatable="false"/>
<Property Name="Ab" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Дата начала"/>
<Property Name="Bis" Type="Edm.DateTime" Precision="0" sap:display-format="Date" sap:label="Дата конца"/>
<Property Name="Price" Type="Edm.Decimal" Precision="11" Scale="3" sap:label="Цена"/>
<Property Name="Curr" Type="Edm.String" MaxLength="3" sap:display-format="UpperCase" sap:label="Валюта"/>
<Property Name="Amount" Type="Edm.String" MaxLength="6" sap:display-format="NonNegative" sap:label="Количество"/>
<NavigationProperty Name="to_chartamount" Relationship="ZGUT_CDS_FIORY_CDS.assoc_17D58845CCECEF801599D15F5569B65F" FromRole="FromRole_assoc_17D58845CCECEF801599D15F5569B65F" ToRole="ToRole_assoc_17D58845CCECEF801599D15F5569B65F"/>
<NavigationProperty Name="to_chartamount2" Relationship="ZGUT_CDS_FIORY_CDS.assoc_84AF2B5FF9693A0A2F011CFC2072B09A" FromRole="FromRole_assoc_84AF2B5FF9693A0A2F011CFC2072B09A" ToRole="ToRole_assoc_84AF2B5FF9693A0A2F011CFC2072B09A"/>
</EntityType>
<EntityType Name="ZGUT_CHART_AMOUNTType" sap:semantics="aggregate" sap:label="ZGUT_CHART_AMOUNT" sap:content-version="1">
<Key>
<PropertyRef Name="ID"/>
</Key>
<Property Name="ID" Type="Edm.String" Nullable="false"/>
<Property Name="Ids" Type="Edm.String" MaxLength="6" sap:aggregation-role="dimension" sap:display-format="NonNegative" sap:label="Номер"/>
<Property Name="Amounts" Type="Edm.String" MaxLength="6" sap:aggregation-role="measure" sap:display-format="NonNegative" sap:label="Количество" sap:filterable="false"/>
<Property Name="target_amount" Type="Edm.String" MaxLength="6" sap:aggregation-role="dimension" sap:display-format="NonNegative" sap:label="Количество"/>
<Property Name="Price" Type="Edm.Decimal" Precision="11" Scale="3" sap:aggregation-role="dimension" sap:label="Цена"/>
<Property Name="Curr" Type="Edm.String" MaxLength="3" sap:aggregation-role="dimension" sap:display-format="UpperCase" sap:label="Валюта"/>
</EntityType>
<Association Name="assoc_84AF2B5FF9693A0A2F011CFC2072B09A" sap:content-version="1">
<End Type="ZGUT_CDS_FIORY_CDS.ZGUT_CDS_FIORYType" Multiplicity="1" Role="FromRole_assoc_84AF2B5FF9693A0A2F011CFC2072B09A"/>
<End Type="ZGUT_CDS_FIORY_CDS.ZGUT_CHART_AMOUNTType" Multiplicity="1" Role="ToRole_assoc_84AF2B5FF9693A0A2F011CFC2072B09A"/>
</Association>
<Association Name="assoc_17D58845CCECEF801599D15F5569B65F" sap:content-version="1">
<End Type="ZGUT_CDS_FIORY_CDS.ZGUT_CDS_FIORYType" Multiplicity="1" Role="FromRole_assoc_17D58845CCECEF801599D15F5569B65F"/>
<End Type="ZGUT_CDS_FIORY_CDS.ZGUT_CHART_AMOUNTType" Multiplicity="*" Role="ToRole_assoc_17D58845CCECEF801599D15F5569B65F"/>
</Association>
<EntityContainer Name="ZGUT_CDS_FIORY_CDS_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
<EntitySet Name="ZGUT_CDS_FIORY" EntityType="ZGUT_CDS_FIORY_CDS.ZGUT_CDS_FIORYType" sap:searchable="true" sap:content-version="1"/>
<EntitySet Name="ZGUT_CHART_AMOUNT" EntityType="ZGUT_CDS_FIORY_CDS.ZGUT_CHART_AMOUNTType" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1"/>
<AssociationSet Name="assoc_17D58845CCECEF801599D15F5569B65F" Association="ZGUT_CDS_FIORY_CDS.assoc_17D58845CCECEF801599D15F5569B65F" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
<End EntitySet="ZGUT_CDS_FIORY" Role="FromRole_assoc_17D58845CCECEF801599D15F5569B65F"/>
<End EntitySet="ZGUT_CHART_AMOUNT" Role="ToRole_assoc_17D58845CCECEF801599D15F5569B65F"/>
</AssociationSet>
<AssociationSet Name="assoc_84AF2B5FF9693A0A2F011CFC2072B09A" Association="ZGUT_CDS_FIORY_CDS.assoc_84AF2B5FF9693A0A2F011CFC2072B09A" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
<End EntitySet="ZGUT_CDS_FIORY" Role="FromRole_assoc_84AF2B5FF9693A0A2F011CFC2072B09A"/>
<End EntitySet="ZGUT_CHART_AMOUNT" Role="ToRole_assoc_84AF2B5FF9693A0A2F011CFC2072B09A"/>
</AssociationSet>
</EntityContainer>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="self" href="http://host:50000/sap/opu/odata/sap/ZGUT_CDS_FIORY_CDS/$metadata"/>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="latest-version" href="http://host:50000/sap/opu/odata/sap/ZGUT_CDS_FIORY_CDS/$metadata"/>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
I solved the issue by choosing the exporting type in the actions list and reactivate the bopf

RESTier OData Function that support $expand and $filter

With the help of the RESTier team, I manage to create an RESTier function that return a list of my entity.
Here's the code
protected EdmModel OnModelExtending(EdmModel model)
{
var ns = model.DeclaredNamespaces.First(); // PointLoc.Data
var entityContainer = (EdmEntityContainer) model.EntityContainer;
var locationEntityType = (IEdmEntityType) model.FindDeclaredType(ns + "." + "Location");
var locationEntitySet = entityContainer.FindEntitySet("Locations");
var locationEntityTypeReference = new EdmEntityTypeReference(locationEntityType, false);
var locationEntityCollection = EdmCoreModel.GetCollection(locationEntityTypeReference);
var ambilLocationsByMarketId = new EdmFunction(ns, "AmbilLocationsByMarketId", locationEntityCollection, false, null, true);
model.AddElement(ambilLocationsByMarketId);
entityContainer.AddFunctionImport("AmbilLocationsByMarketId", ambilLocationsByMarketId,
new EdmEntitySetReferenceExpression(locationEntitySet));
return model;
}
And here's my implementation on the Controller
[HttpGet]
[EnableQuery]
[ODataRoute("AmbilLocationsByMarketId")]
public IQueryable<Location> AmbilLocationsByMarketId()
{
var locations = DbContext.Locations.Where(l => l.Name.Contains("Hotel")).Select(l => l);
return locations;
}
It works fine returning the list of data with i send a HTTP GET to
http://localhost:21922/odata/AmbilLocationsByMarketId
but when I try to add $expand or $filter, It's not working.
http://localhost:21922/odata/AmbilLocationsByMarketId?$expand=Category
I'm Error that reads like
{
"error": {
"code": "",
"message": "An error has occurred.",
"innererror": {
"message": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.",
"type": "System.InvalidOperationException",
"stacktrace": "",
"internalexception": {
"message": "'DbQuery`1' cannot be serialized using the ODataMediaTypeFormatter.",
"type": "System.Runtime.Serialization.SerializationException",
"stacktrace": " at System.Web.OData.Formatter.ODataMediaTypeFormatter.GetSerializer(Type type, Object value, IEdmModel model, ODataSerializerProvider serializerProvider)\\\r\\\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\\\r\\\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\\\r\\\n--- End of stack trace from previous location where exception was thrown ---\\\r\\\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\\\r\\\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\\\r\\\n at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\\\r\\\n at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"
}
}
}
}
Here's my metadata
<EntityType Name="Location">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false">
<Annotation Term="Org.OData.Core.V1.Computed" Bool="true" />
</Property>
<Property Name="Name" Type="Edm.String" Nullable="false" MaxLength="500" />
<Property Name="Address" Type="Edm.String" Nullable="false" MaxLength="2000" />
<Property Name="City" Type="Edm.String" MaxLength="500" />
<Property Name="Postcode" Type="Edm.String" MaxLength="100" />
<Property Name="Phone" Type="Edm.String" MaxLength="50" />
<Property Name="Email" Type="Edm.String" MaxLength="200" />
<Property Name="Latitude" Type="Edm.Decimal" Nullable="false" Precision="9" Scale="6" />
<Property Name="Longitude" Type="Edm.Decimal" Nullable="false" Precision="9" Scale="6" />
<Property Name="Street" Type="Edm.String" MaxLength="1000" />
<Property Name="UpVotes" Type="Edm.Int32" Nullable="false" />
<Property Name="DownVotes" Type="Edm.Int32" Nullable="false" />
<Property Name="CategoryId" Type="Edm.Int32" Nullable="false" />
<Property Name="StatusId" Type="Edm.Int32" Nullable="false" />
<Property Name="StateId" Type="Edm.Int32" Nullable="false" />
<Property Name="TitleSlug" Type="Edm.String" MaxLength="200" />
<NavigationProperty Name="Category" Type="PointLoc.Data.Category" Nullable="false" Partner="Locations">
<ReferentialConstraint Property="CategoryId" ReferencedProperty="Id" />
</NavigationProperty>
</EntityType>
and here's the EntityContainer
<EntityContainer Name="DatabaseContext">
<EntitySet Name="Categories" EntityType="PointLoc.Data.Category">
<NavigationPropertyBinding Path="Locations" Target="Locations" />
</EntitySet>
<EntitySet Name="Locations" EntityType="PointLoc.Data.Location">
<NavigationPropertyBinding Path="Accesses" Target="Accesses" />
<NavigationPropertyBinding Path="Category" Target="Categories" />
<NavigationPropertyBinding Path="Contents" Target="Contents" />
<NavigationPropertyBinding Path="State" Target="States" />
<NavigationPropertyBinding Path="Status" Target="Status" />
<NavigationPropertyBinding Path="LocationMarketMaps" Target="LocationMarketMaps" />
<NavigationPropertyBinding Path="LocationTagMaps" Target="LocationTagMaps" />
</EntitySet>
<FunctionImport Name="AmbilLocationsByMarketId" Function="PointLoc.Data.AmbilLocationsByMarketId" EntitySet="Locations" />
</EntityContainer>

Custom UserDetailsService in spring-security

I cant proceed further into my project because of an strange error. I am trying to implement spring-security and spring data JPA for my application, which exposes only REST api.
Now, when I am trying to implement my custom UserDetailsService class, as mentioned below, the parameter username in method loadUserByUsername is not the username I am passing as a POST request parameter, rather its the client_id parameter.
Can someone please suggest as what am I doing wrong?
public class CustomUserDetailsService implements UserDetailsService {
private ClientDetailsService clientDetailsService;
private String emptyPassword = "";
public CustomUserDetailsService() {
}
public CustomUserDetailsService(ClientDetailsService clientDetailsService) {
this.clientDetailsService = clientDetailsService;
}
private List<GrantedAuthority> getAuthorities(String role) {
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
// you can also add different roles here
// for example, the user is also an admin of the site, then you can add
// ROLE_ADMIN
// so that he can view pages that are ROLE_ADMIN specific
if (role != null && role.trim().length() > 0) {
if (role.equals("admin")) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
}
return authList;
}
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
ClientDetails clientDetails = clientDetailsService
.loadClientByClientId(username);
String clientSecret = clientDetails.getClientSecret();
if (clientSecret == null || clientSecret.trim().length() == 0) {
clientSecret = emptyPassword;
}
return new User(username, clientSecret, clientDetails.getAuthorities());
}
}
My spring-security configuration is as following:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd ">
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/api/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/logout" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout"
success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="logoutSuccessHandler" class="com.monsor.feasthub.security.LogoutImpl">
<property name="tokenstore" ref="tokenStore" />
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />
<bean id="applicationContextProvder" class="com.monsor.feasthub.util.ApplicationContextProvider" />
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<bean id="clientDetailsUserService" class="com.monsor.feasthub.security.CustomUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.monsor.feasthub.security.ClientDetailsServiceImpl" />
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password authentication-manager-ref="userAuthenticationManager" />
</oauth:authorization-server>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="customUserAuthenticationProvider" />
</authentication-manager>
<bean id="customUserAuthenticationProvider"
class="com.monsor.feasthub.security.CustomUserAuthenticationProvider" />
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="300000" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<mvc:annotation-driven /> <!-- Declares explicit support for annotation-driven MVC controllers #RequestMapping,
#Controller -->
<mvc:default-servlet-handler />
<bean id="MyResource" class="com.monsor.feasthub.resources.MyResource" />
</beans>

"An item with the same key has already been added" error when calling Context AddObject

Can somebody please help me with this error. I have an ASP.NET WebApp, within the Entity Model I have an entity called tb_AdminUser, with a UserID property as GUID. This is also the Entity Key. The entity is not in any relationship with any other entity. I get the error when calling the AddObject() function.
In my code I call the following...
SQL2008R2_824852_leapdbEntities temp = new SQL2008R2_824852_leapdbEntities();
tb_AdminUser au = new tb_AdminUser();
au.UserID = Guid.NewGuid();
au.Username = "TEST";
au.Password = "pete#webinspired.net";
au.LockedOut = false;
au.Surname = "Feehan";
au.Forename = "Pete";
temp.tb_AdminUser.AddObject(au); //error occurs here
temp.SaveChanges();
The EDMX XML Code is as follows
<EntityType Name="tb_AdminUser">
<Key>
<PropertyRef Name="UserID" />
</Key>
<Property Name="UserID" Type="uniqueidentifier" Nullable="false" />
<Property Name="Forename" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Surname" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Username" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="Password" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="LockedOut" Type="bit" Nullable="false" />
</EntityType>

Add child to existing parent record in entity framework

My relationship between the parent and child is that they are connected by an edge. It is similiar to a directed graph structure.
DAL:
public void SaveResource(Resource resource)
{
context.AddToResources(resource); //Should also add children.
context.SaveChanges();
}
public Resource GetResource(int resourceId)
{
var resource = (from r in context.Resources
.Include("ToEdges").Include("FromEdges")
where r.ResourceId == resourceId
select r).SingleOrDefault();
return resource;
}
Service:
public void AddChildResource(int parentResourceId, Resource childResource)
{
Resource parentResource = repository.GetResource(parentResourceId);
ResourceEdge inEdge = new ResourceEdge();
inEdge.ToResource = childResource;
parentResource.ToEdges.Add(inEdge);
repository.SaveResource(parentResource);
}
Error: An object with the same key already exists in the ObjectStateManager. The existing object is in the Unchanged state. An object can only be added to the ObjectStateManager again if it is in the added state.
Image:
I have been told this is the sequence in submitting a child to an already existing parent:
Get parent -> Attach Child to parent -> submit parent.
That is the sequence I used. The code above is extracted from an ASP.NET MVC 2 application using the repository pattern.
EDMX file:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="2.0" xmlns:edmx="http://schemas.microsoft.com/ado/2008/10/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="XDbModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="XDbModelStoreContainer">
<EntitySet Name="Bundles" EntityType="XDbModel.Store.Bundles" store:Type="Tables" Schema="dbo" />
<EntitySet Name="CellProviders" EntityType="XDbModel.Store.CellProviders" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Comments" EntityType="XDbModel.Store.Comments" store:Type="Tables" Schema="dbo" />
<EntitySet Name="LocationPoints" EntityType="XDbModel.Store.LocationPoints" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Locations" EntityType="XDbModel.Store.Locations" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Offers" EntityType="XDbModel.Store.Offers" store:Type="Tables" Schema="dbo" />
<EntitySet Name="PostBundleJunction" EntityType="XDbModel.Store.PostBundleJunction" store:Type="Tables" Schema="dbo" />
<EntitySet Name="PostMedia" EntityType="XDbModel.Store.PostMedia" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Posts" EntityType="XDbModel.Store.Posts" store:Type="Tables" Schema="dbo" />
<EntitySet Name="ResourceEdges" EntityType="XDbModel.Store.ResourceEdges" store:Type="Tables" Schema="dbo" />
<EntitySet Name="ResourceNames" EntityType="XDbModel.Store.ResourceNames" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Resources" EntityType="XDbModel.Store.Resources" store:Type="Tables" Schema="dbo" />
<EntitySet Name="sysdiagrams" EntityType="XDbModel.Store.sysdiagrams" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Users" EntityType="XDbModel.Store.Users" store:Type="Tables" Schema="dbo" />
<EntitySet Name="Votes" EntityType="XDbModel.Store.Votes" store:Type="Tables" Schema="dbo" />
<AssociationSet Name="FK_Comments_Offers" Association="XDbModel.Store.FK_Comments_Offers">
<End Role="Offers" EntitySet="Offers" />
<End Role="Comments" EntitySet="Comments" />
</AssociationSet>
<AssociationSet Name="FK_Comments_Users" Association="XDbModel.Store.FK_Comments_Users">
<End Role="Users" EntitySet="Users" />
<End Role="Comments" EntitySet="Comments" />
</AssociationSet>
<AssociationSet Name="FK_LocationPoints_Locations" Association="XDbModel.Store.FK_LocationPoints_Locations">
<End Role="Locations" EntitySet="Locations" />
<End Role="LocationPoints" EntitySet="LocationPoints" />
</AssociationSet>
<AssociationSet Name="FK_PostBundleJunction_Bundles" Association="XDbModel.Store.FK_PostBundleJunction_Bundles">
<End Role="Bundles" EntitySet="Bundles" />
<End Role="PostBundleJunction" EntitySet="PostBundleJunction" />
</AssociationSet>
<AssociationSet Name="FK_PostBundleJunction_Posts" Association="XDbModel.Store.FK_PostBundleJunction_Posts">
<End Role="Posts" EntitySet="Posts" />
<End Role="PostBundleJunction" EntitySet="PostBundleJunction" />
</AssociationSet>
<AssociationSet Name="FK_Posts_Locations" Association="XDbModel.Store.FK_Posts_Locations">
<End Role="Locations" EntitySet="Locations" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
<AssociationSet Name="FK_Posts_ResourceNames" Association="XDbModel.Store.FK_Posts_ResourceNames">
<End Role="ResourceNames" EntitySet="ResourceNames" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
<AssociationSet Name="FK_Posts_Users" Association="XDbModel.Store.FK_Posts_Users">
<End Role="Users" EntitySet="Users" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
<AssociationSet Name="FK_ResourceEdges_Resources" Association="XDbModel.Store.FK_ResourceEdges_Resources">
<End Role="Resources" EntitySet="Resources" />
<End Role="ResourceEdges" EntitySet="ResourceEdges" />
</AssociationSet>
<AssociationSet Name="FK_ResourceEdges_Resources1" Association="XDbModel.Store.FK_ResourceEdges_Resources1">
<End Role="Resources" EntitySet="Resources" />
<End Role="ResourceEdges" EntitySet="ResourceEdges" />
</AssociationSet>
<AssociationSet Name="FK_ResourceNames_Resources" Association="XDbModel.Store.FK_ResourceNames_Resources">
<End Role="Resources" EntitySet="Resources" />
<End Role="ResourceNames" EntitySet="ResourceNames" />
</AssociationSet>
<AssociationSet Name="FK_Users_Locations" Association="XDbModel.Store.FK_Users_Locations">
<End Role="Locations" EntitySet="Locations" />
<End Role="Users" EntitySet="Users" />
</AssociationSet>
<AssociationSet Name="FK_Votes_Posts" Association="XDbModel.Store.FK_Votes_Posts">
<End Role="Posts" EntitySet="Posts" />
<End Role="Votes" EntitySet="Votes" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Bundles">
<Key>
<PropertyRef Name="BundleId" />
</Key>
<Property Name="BundleId" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="CellProviders">
<Key>
<PropertyRef Name="CellProviderID" />
</Key>
<Property Name="CellProviderID" Type="uniqueidentifier" Nullable="false" />
</EntityType>
<EntityType Name="Comments">
<Key>
<PropertyRef Name="CommentID" />
</Key>
<Property Name="CommentID" Type="uniqueidentifier" Nullable="false" />
<Property Name="ParentPostID" Type="uniqueidentifier" />
<Property Name="OfferPostID" Type="uniqueidentifier" />
<Property Name="UserID" Type="uniqueidentifier" Nullable="false" />
</EntityType>
<EntityType Name="LocationPoints">
<Key>
<PropertyRef Name="LocationPointId" />
</Key>
<Property Name="LocationPointId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="Latitude" Type="float" Nullable="false" />
<Property Name="Longitude" Type="float" Nullable="false" />
<Property Name="Altitude" Type="float" Nullable="false" />
<Property Name="Count" Type="int" Nullable="false" />
<Property Name="LocationId" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="Locations">
<Key>
<PropertyRef Name="LocationId" />
</Key>
<Property Name="LocationId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="Address1" Type="nvarchar" Nullable="false" MaxLength="200" />
<Property Name="Address2" Type="nvarchar" MaxLength="200" />
<Property Name="Address3" Type="nvarchar" MaxLength="200" />
<Property Name="State" Type="nvarchar" Nullable="false" MaxLength="200" />
<Property Name="Country" Type="nvarchar" Nullable="false" MaxLength="200" />
</EntityType>
<EntityType Name="Offers">
<Key>
<PropertyRef Name="OfferID" />
</Key>
<Property Name="OfferID" Type="uniqueidentifier" Nullable="false" />
<Property Name="NeedOffer" Type="uniqueidentifier" Nullable="false" />
<Property Name="ProvisionOffer" Type="uniqueidentifier" Nullable="false" />
</EntityType>
<EntityType Name="PostBundleJunction">
<Key>
<PropertyRef Name="BundleId" />
<PropertyRef Name="PostId" />
</Key>
<Property Name="BundleId" Type="int" Nullable="false" />
<Property Name="PostId" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="PostMedia">
<Key>
<PropertyRef Name="MediaId" />
</Key>
<Property Name="MediaId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="MediaExt" Type="nvarchar" Nullable="false" MaxLength="5" />
<Property Name="PostId" Type="int" Nullable="false" />
<Property Name="SynthId" Type="uniqueidentifier" />
</EntityType>
<EntityType Name="Posts">
<Key>
<PropertyRef Name="PostId" />
</Key>
<Property Name="PostId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="PosterID" Type="uniqueidentifier" Nullable="false" />
<Property Name="BundleId" Type="int" Nullable="false" />
<Property Name="LocationId" Type="int" Nullable="false" />
<Property Name="Tags" Type="uniqueidentifier" />
<Property Name="Quanitity" Type="int" Nullable="false" />
<Property Name="Description" Type="text" Nullable="false" />
<Property Name="ResourceNameId" Type="int" Nullable="false" />
<Property Name="Date" Type="datetime" Nullable="false" />
</EntityType>
<EntityType Name="ResourceEdges">
<Key>
<PropertyRef Name="EdgeId" />
</Key>
<Property Name="Rank" Type="int" Nullable="false" />
<Property Name="EdgeId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="ToResourceId" Type="int" Nullable="false" />
<Property Name="FromResourrceId" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="ResourceNames">
<Key>
<PropertyRef Name="ResourceNameId" />
</Key>
<Property Name="ResourceNameId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="100" />
<Property Name="ResourceId" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="Resources">
<Key>
<PropertyRef Name="ResourceId" />
</Key>
<Property Name="ResourceId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="Description" Type="nvarchar" MaxLength="50" />
</EntityType>
<EntityType Name="sysdiagrams">
<Key>
<PropertyRef Name="diagram_id" />
</Key>
<Property Name="name" Type="nvarchar" Nullable="false" MaxLength="128" />
<Property Name="principal_id" Type="int" Nullable="false" />
<Property Name="diagram_id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="version" Type="int" />
<Property Name="definition" Type="varbinary(max)" />
</EntityType>
<EntityType Name="Users">
<Key>
<PropertyRef Name="UserID" />
</Key>
<Property Name="UserID" Type="uniqueidentifier" Nullable="false" />
<Property Name="LocationId" Type="int" />
</EntityType>
<EntityType Name="Votes">
<Key>
<PropertyRef Name="VoteId" />
</Key>
<Property Name="VoteId" Type="int" Nullable="false" />
<Property Name="VoterId" Type="uniqueidentifier" Nullable="false" />
<Property Name="VoteContent" Type="int" Nullable="false" />
<Property Name="PostId" Type="int" Nullable="false" />
</EntityType>
<Association Name="FK_Comments_Offers">
<End Role="Offers" Type="XDbModel.Store.Offers" Multiplicity="0..1" />
<End Role="Comments" Type="XDbModel.Store.Comments" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Offers">
<PropertyRef Name="OfferID" />
</Principal>
<Dependent Role="Comments">
<PropertyRef Name="OfferPostID" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Comments_Users">
<End Role="Users" Type="XDbModel.Store.Users" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
<End Role="Comments" Type="XDbModel.Store.Comments" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Users">
<PropertyRef Name="UserID" />
</Principal>
<Dependent Role="Comments">
<PropertyRef Name="UserID" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_LocationPoints_Locations">
<End Role="Locations" Type="XDbModel.Store.Locations" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
<End Role="LocationPoints" Type="XDbModel.Store.LocationPoints" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Locations">
<PropertyRef Name="LocationId" />
</Principal>
<Dependent Role="LocationPoints">
<PropertyRef Name="LocationId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_PostBundleJunction_Bundles">
<End Role="Bundles" Type="XDbModel.Store.Bundles" Multiplicity="1" />
<End Role="PostBundleJunction" Type="XDbModel.Store.PostBundleJunction" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Bundles">
<PropertyRef Name="BundleId" />
</Principal>
<Dependent Role="PostBundleJunction">
<PropertyRef Name="BundleId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_PostBundleJunction_Posts">
<End Role="Posts" Type="XDbModel.Store.Posts" Multiplicity="1" />
<End Role="PostBundleJunction" Type="XDbModel.Store.PostBundleJunction" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Posts">
<PropertyRef Name="PostId" />
</Principal>
<Dependent Role="PostBundleJunction">
<PropertyRef Name="PostId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Posts_Locations">
<End Role="Locations" Type="XDbModel.Store.Locations" Multiplicity="1" />
<End Role="Posts" Type="XDbModel.Store.Posts" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Locations">
<PropertyRef Name="LocationId" />
</Principal>
<Dependent Role="Posts">
<PropertyRef Name="LocationId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Posts_ResourceNames">
<End Role="ResourceNames" Type="XDbModel.Store.ResourceNames" Multiplicity="1" />
<End Role="Posts" Type="XDbModel.Store.Posts" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="ResourceNames">
<PropertyRef Name="ResourceNameId" />
</Principal>
<Dependent Role="Posts">
<PropertyRef Name="ResourceNameId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Posts_Users">
<End Role="Users" Type="XDbModel.Store.Users" Multiplicity="1" />
<End Role="Posts" Type="XDbModel.Store.Posts" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Users">
<PropertyRef Name="UserID" />
</Principal>
<Dependent Role="Posts">
<PropertyRef Name="PosterID" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_ResourceEdges_Resources">
<End Role="Resources" Type="XDbModel.Store.Resources" Multiplicity="1" />
<End Role="ResourceEdges" Type="XDbModel.Store.ResourceEdges" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Resources">
<PropertyRef Name="ResourceId" />
</Principal>
<Dependent Role="ResourceEdges">
<PropertyRef Name="ToResourceId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_ResourceEdges_Resources1">
<End Role="Resources" Type="XDbModel.Store.Resources" Multiplicity="1" />
<End Role="ResourceEdges" Type="XDbModel.Store.ResourceEdges" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Resources">
<PropertyRef Name="ResourceId" />
</Principal>
<Dependent Role="ResourceEdges">
<PropertyRef Name="FromResourrceId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_ResourceNames_Resources">
<End Role="Resources" Type="XDbModel.Store.Resources" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
<End Role="ResourceNames" Type="XDbModel.Store.ResourceNames" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Resources">
<PropertyRef Name="ResourceId" />
</Principal>
<Dependent Role="ResourceNames">
<PropertyRef Name="ResourceId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Users_Locations">
<End Role="Locations" Type="XDbModel.Store.Locations" Multiplicity="0..1">
<OnDelete Action="Cascade" />
</End>
<End Role="Users" Type="XDbModel.Store.Users" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Locations">
<PropertyRef Name="LocationId" />
</Principal>
<Dependent Role="Users">
<PropertyRef Name="LocationId" />
</Dependent>
</ReferentialConstraint>
</Association>
<Association Name="FK_Votes_Posts">
<End Role="Posts" Type="XDbModel.Store.Posts" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
<End Role="Votes" Type="XDbModel.Store.Votes" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Posts">
<PropertyRef Name="PostId" />
</Principal>
<Dependent Role="Votes">
<PropertyRef Name="PostId" />
</Dependent>
</ReferentialConstraint>
</Association>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="XDbModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityContainer Name="XDbEntities" annotation:LazyLoadingEnabled="true">
<EntitySet Name="Bundles" EntityType="XDbModel.Bundle" />
<EntitySet Name="CellProviders" EntityType="XDbModel.CellProvider" />
<EntitySet Name="Comments" EntityType="XDbModel.Comment" />
<EntitySet Name="LocationPoints" EntityType="XDbModel.LocationPoint" />
<EntitySet Name="Locations" EntityType="XDbModel.Location" />
<EntitySet Name="Offers" EntityType="XDbModel.Offer" />
<EntitySet Name="PostMedias" EntityType="XDbModel.PostMedia" />
<EntitySet Name="Posts" EntityType="XDbModel.Post" />
<EntitySet Name="ResourceEdges" EntityType="XDbModel.ResourceEdge" />
<EntitySet Name="ResourceNames" EntityType="XDbModel.ResourceName" />
<EntitySet Name="Resources" EntityType="XDbModel.Resource" />
<EntitySet Name="sysdiagrams" EntityType="XDbModel.sysdiagram" />
<EntitySet Name="Users" EntityType="XDbModel.User" />
<EntitySet Name="Votes" EntityType="XDbModel.Vote" />
<AssociationSet Name="FK_Comments_Offers" Association="XDbModel.FK_Comments_Offers">
<End Role="Offers" EntitySet="Offers" />
<End Role="Comments" EntitySet="Comments" />
</AssociationSet>
<AssociationSet Name="FK_Comments_Users" Association="XDbModel.FK_Comments_Users">
<End Role="Users" EntitySet="Users" />
<End Role="Comments" EntitySet="Comments" />
</AssociationSet>
<AssociationSet Name="FK_LocationPoints_Locations" Association="XDbModel.FK_LocationPoints_Locations">
<End Role="Locations" EntitySet="Locations" />
<End Role="LocationPoints" EntitySet="LocationPoints" />
</AssociationSet>
<AssociationSet Name="FK_Posts_Locations" Association="XDbModel.FK_Posts_Locations">
<End Role="Locations" EntitySet="Locations" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
<AssociationSet Name="FK_Users_Locations" Association="XDbModel.FK_Users_Locations">
<End Role="Locations" EntitySet="Locations" />
<End Role="Users" EntitySet="Users" />
</AssociationSet>
<AssociationSet Name="FK_Posts_ResourceNames" Association="XDbModel.FK_Posts_ResourceNames">
<End Role="ResourceNames" EntitySet="ResourceNames" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
<AssociationSet Name="FK_Posts_Users" Association="XDbModel.FK_Posts_Users">
<End Role="Users" EntitySet="Users" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
<AssociationSet Name="FK_Votes_Posts" Association="XDbModel.FK_Votes_Posts">
<End Role="Posts" EntitySet="Posts" />
<End Role="Votes" EntitySet="Votes" />
</AssociationSet>
<AssociationSet Name="FK_ResourceEdges_Resources" Association="XDbModel.FK_ResourceEdges_Resources">
<End Role="Resources" EntitySet="Resources" />
<End Role="ResourceEdges" EntitySet="ResourceEdges" />
</AssociationSet>
<AssociationSet Name="FK_ResourceEdges_Resources1" Association="XDbModel.FK_ResourceEdges_Resources1">
<End Role="Resources" EntitySet="Resources" />
<End Role="ResourceEdges" EntitySet="ResourceEdges" />
</AssociationSet>
<AssociationSet Name="FK_ResourceNames_Resources" Association="XDbModel.FK_ResourceNames_Resources">
<End Role="Resources" EntitySet="Resources" />
<End Role="ResourceNames" EntitySet="ResourceNames" />
</AssociationSet>
<AssociationSet Name="PostBundleJunction" Association="XDbModel.PostBundleJunction">
<End Role="Bundles" EntitySet="Bundles" />
<End Role="Posts" EntitySet="Posts" />
</AssociationSet>
</EntityContainer>
<EntityType Name="Bundle">
<Key>
<PropertyRef Name="BundleId" />
</Key>
<Property Name="BundleId" Type="Int32" Nullable="false" />
<NavigationProperty Name="Posts" Relationship="XDbModel.PostBundleJunction" FromRole="Bundles" ToRole="Posts" />
</EntityType>
<EntityType Name="CellProvider">
<Key>
<PropertyRef Name="CellProviderID" />
</Key>
<Property Name="CellProviderID" Type="Guid" Nullable="false" />
</EntityType>
<EntityType Name="Comment">
<Key>
<PropertyRef Name="CommentID" />
Ah, it's actually very simple, once you think about it..
What you're trying to do it add the resource to the data context, even though this resource object was received from the database in the first place. So the error is not complaining about your child objects, but about your parent object! :)
Basically if you comment the first line in the SaveResource() method it should just work fine!
E.g.:
public void SaveResource(Resource resource)
{
// context.AddToResources(resource); //Should also add children.
context.SaveChanges();
}
Or just move the AddChildResource method to your DAL:
public void AddChildResource(int parentResourceId, Resource childResource)
{
Resource parentResource = repository.GetResource(parentResourceId);
ResourceEdge inEdge = new ResourceEdge();
inEdge.ToResource = childResource;
parentResource.ToEdges.Add(inEdge);
context.SaveChanges();
}
Presumably it's complaining about the childResource not being in the added state. You added it to the edge object that is in the added state.
Can you try flipping the way you set that association round:-
public void AddChildResource(int parentResourceId, Resource childResource)
{
Resource parentResource = repository.GetResource(parentResourceId);
ResourceEdge inEdge = new ResourceEdge();
// inEdge.ToResource = childResource; <-- don't do this
parentResource.ToEdges.Add(inEdge);
childResource.FromEdges.Add(inEdge); // try this instead
repository.SaveResource(parentResource);
}

Resources