breeze - One to many navigation property not working -


i using breezejs v.1.5.4 odata web api controllers (and angularjs v.1.4.0 if makes difference).

i have following models (simplified):

public partial class job {     ...      [required]     [stringlength(128)]     [index("ix_workdonebyid")]     [display(name = "work done id")]     public string workdonebyid { get; set; }      [foreignkey("workdonebyid")]     public virtual user workdoneby { get; set; } }  [datacontract] public partial class user : identityuser {     ...      [key]     [stringlength(128)]     [display(name = "id")]     [datamember]     public override string id     {                 {             return base.id;         }         set         {             base.id = value;         }     }      [inverseproperty("workdoneby")]     [datamember]     public virtual icollection<job> jobs { get; set; } } 

when trying job information , expanding workdoneby, works , user information (i.e. user binded job). while when try jobs associated user, empty array. inspected network , jobs transmitted server response not attached user instance.

my js query this:

var query = new breeze.entityquery()             .from("users")             .expand("jobs")             .where(new breeze.predicate("id", "eq", "some long guid")); 

any suggestions ??

update 1

also using datajs v.1.1.3 , odata service adapter.

below metadata:

{ "metadataversion": "1.0.5", "namingconvention": "nochange", "localquerycomparisonoptions": "caseinsensitivesql", "dataservices": [     {         "servicename": "odata/",         "adaptername": "odata",         "uribuildername": "odata",         "hasservermetadata": true,         "jsonresultsadapter": "odata_default",         "usejsonp": false     } ], "structuraltypes": [     {         "shortname": "job",          "namespace": "myapp.models",         "autogeneratedkeytype": "none",          "defaultresourcename": "jobs",          "dataproperties": [             {                  "name": "jobid",                  "datatype": "guid",                  "isnullable": false,                  "defaultvalue": "00000000-0000-0000-0000-000000000000",                  "ispartofkey": true,                  "validators": [{ "name": "required" }, { "name": "guid" }]              },              {                  "name": "workdonebyid",                  "datatype": "string",                  "isnullable": false,                  "defaultvalue": "",                  "validators": [{ "name": "required" }, { "name": "string" }]              }         ],         "navigationproperties": [             {                  "name": "workdoneby",                  "entitytypename": "user:#myapp.models",                  "isscalar": true,                  "associationname": "myapp_models_job_workdoneby_myapp_models_user_workdonebypartner"              }         ]     },     {         "shortname": "user",          "namespace": "myapp.models",         "autogeneratedkeytype": "none",          "defaultresourcename": "users",          "dataproperties": [             {                  "name": "id",                  "datatype": "string",                  "isnullable": false,                  "defaultvalue": "",                  "ispartofkey": true,                  "validators": [{ "name": "required" }, { "name": "string" }]              }         ],          "navigationproperties": [             {                  "name": "jobs",                  "entitytypename": "job:#myapp.models",                  "isscalar": false,                  "associationname": "myapp_models_user_jobs_myapp_models_job_jobspartner"              }         ]     } ], "resourceentitytypemap": {     "jobs": "job:#myapp.models",     "users": "user:#myapp.models" } } 

and breeze configuration:

var dataservice = new breeze.dataservice({     adaptername: "odata",     hasservermetadata: false,  // don't ask server metadata      servicename: "odata",     uribuildername: "odata", });  // create metadatastore  var metadatastore = new breeze.metadatastore();  // initialize store application's metadata variable metadatastore.importmetadata(models.metadata);  // apply additional functions , properties models metadatastore.registerentitytypector("job", models.job); metadatastore.registerentitytypector("user", models.user);  // initializes entity manager. this.entitymanager = new breeze.entitymanager(     { dataservice: dataservice, metadatastore: metadatastore } ); 

update 2

metadata generated server odata/$metadata:

<edmx:edmx version="1.0">   <edmx:dataservices m:dataserviceversion="3.0" m:maxdataserviceversion="3.0">     <schema namespace="myapp.models">       <entitytype name="job">         <key>           <propertyref name="jobid"/>         </key>         <property name="jobid" type="edm.guid" nullable="false"/>         <property name="workdonebyid" type="edm.string" nullable="false"/>         <navigationproperty name="workdoneby" relationship="myapp.models.myapp_models_job_workdoneby_myapp_models_user_workdonebypartner" torole="workdoneby" fromrole="workdonebypartner"/>       </entitytype>       <entitytype name="user">         <key>           <propertyref name="id"/>         </key>         <property name="id" type="edm.string" nullable="false"/>         <navigationproperty name="jobs" relationship="myapp.models.myapp_models_user_jobs_myapp_models_job_jobspartner" torole="jobs" fromrole="jobspartner"/>       </entitytype>       <association name="myapp_models_job_workdoneby_myapp_models_user_workdonebypartner">         <end type="myapp.models.user" role="workdoneby" multiplicity="0..1"/>         <end type="myapp.models.job" role="workdonebypartner" multiplicity="0..1"/>       </association>       <association name="myapp_models_user_jobs_myapp_models_job_jobspartner">         <end type="myapp.models.job" role="jobs" multiplicity="*"/>         <end type="myapp.models.user" role="jobspartner" multiplicity="0..1"/>       </association>     </schema>     <schema namespace="default">       <entitycontainer name="container" m:isdefaultentitycontainer="true">         <entityset name="jobs" entitytype="myapp.models.job"/>         <entityset name="users" entitytype="myapp.models.user"/>         <associationset name="myapp_models_job_workdoneby_myapp_models_user_workdonebypartnerset" association="myapp.models.myapp_models_job_workdoneby_myapp_models_user_workdonebypartner">           <end role="workdonebypartner" entityset="jobs"/>           <end role="workdoneby" entityset="users"/>         </associationset>         <associationset name="myapp_models_user_jobs_myapp_models_job_jobspartnerset" association="myapp.models.myapp_models_user_jobs_myapp_models_job_jobspartner">           <end role="jobspartner" entityset="users"/>           <end role="jobs" entityset="jobs"/>         </associationset>       </entitycontainer>     </schema>   </edmx:dataservices> </edmx:edmx> 

according configuration code, appear using locally defined metadata

although it's bit confusing because metadata object shown earlier in question attached dataservice says "hasservermetadata": true. don't know inner dataservice matters.

i'm not positive suspect problem association names; different 2 navigation properties:

    // job     ...     "navigationproperties": [         {              "name": "workdoneby",              ...             "associationname": "myapp_models_job_workdoneby_myapp_models_user_workdonebypartner"          }     ]       // user      ...     "navigationproperties": [         {              "name": "jobs",               ...             "associationname": "myapp_models_user_jobs_myapp_models_job_jobspartner"          }     ] 

if want breeze pair these properties, associationname must same string value. value doesn't matter; fact both property ends of relationship have same associationname. that's how breeze learns these properties mated.

try nice , short spells out underlying relationship ... "user_jobs" or "job.workdoneby_user.jobs"

update #1

it mystery how got different associationname values.

in comment asked @ raw metadata coming odata source.

here example "odatabreezejssample" gets metadata odata v.3 source.

the odata nuget package "microsoft.aspnet.webapi.odata" version="5.2.2". sample uses edmbuilder class as explained in documentation

there 2 types - todolist , todoitem - have one-to-many relationship. pertinent raw metadata xml is:

// todolist <navigationproperty name="todoitems" relationship="odatabreezejssample.models.todolist_todoitems" ... /> // todoitem <navigationproperty name="todolist" relationship="odatabreezejssample.models.todolist_todoitems" ... /> 

note have same relationship name: "odatabreezejssample.models.todolist_todoitems"

then inspect corresponding navigation properties in client-side metadata breeze produces xml. both properties share associationname of "todolist_todoitems" ... equal relationship name stripped of namespace.

what kind of odata source (and odata version) querying? using edmbuilder class generate metadata?

update #2

so you're using "microsoft asp.net web api 2.2 odata v4.0" v.5.6 nuget package! means you're using odata v.4.

what pita!

this huge breaking change v.5.5.x, last of odata v.3 nuget packages.

how make big leap , re-use version numbers, especialy major version digit? boggles mind.

to confuse things, there 2 nuget package names different:

did happen notice "webapi" in middle of v.3 package name? didn't @ first.

the bad news implementation of v.4 broke ... again ... including metadata. , ... again ... failed follow odata spec, w/r/t navigation properties in metadata.

consequently, breeze not yet work web api odata v.4 metadata ... , there other problems well.

we in process of working through issues microsoft odata team. until then, you're options wait or go odata v.3.

also critical: datajs 3rd party client-side javascript library have used odata v.1-3 not work odata v.4. else, you'll have switch olingo library. may olingo library plays constructive role in rationalizing navigation property metadata. don't know , our expert on subject not available @ moment.

yes ... mess.


Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -