i´m using the Papa's course CCJS code to investigate Breeze.js and SPA. Using this code i´m trying to manage aditional information that cames from server but that is not an Entity contained in the Metadata that cames from EntityFramework.
So i created a NO-DB class called Esto and a Server method like Lookups:
[HttpGet]
public object Informacion()
{
var a = new Esto(....);
var b = new Esto(.....);
var c = new Esto(......);
return new {a,b,c};
}
then in model.js inside configureMetadataStore i call:
metadataStore.addEntityType({
shortName: "Esto",
namespace:"CodeCamper",
dataProperties:{
id: {dataType: breeze.DataType.Int32,isPartOfKey: true},
name: {dataType: breeze.DataType.String}
}
};
and also define in the model entityNames array: esto:'Esto' as an Entity
now in the context.js i load this creating a server side method like getLookups but called getInformacion:
function getInformacion(){
return EntityQuery.from('Informacion')
.using(manager).execute()
}
and then inside primeData in the success method call this:
datacontext.informacion = {
esto: getLocal('Esto',nombre)};
where getLocal is:
function getLocal(resource, ordering)
{
var query = EntityQuery.from(resource).orderBy(ordering);
return manager.executeQueryLocally(query);
}
I get an error in the query contained in the getLocal that states that Can not find EntityType for either entityTypeName: 'undefined' or resourceName:'Esto'.
What i´m doing wrong?
Thanks
You were almost there! :-) Had you specified the target EntityType
in the query I think it would have worked.
Try this:
var query = EntityQuery.from(resource).orderBy(ordering).toType('Esto');
The toType()
method tells Breeze that the top-level objects returned by this query will be of type Esto
.
Let's think about how Breeze interprets a query specification.
Notice that you began your query, as we usually do, by naming the resource which will supply the data. This resource is typically a path segment to a remote service endpoint, perhaps the name of a Web API controller method ... a method named "Foos".
It's critical to understand that the query resource name is rarely the same as the EntityType
name! They may be similar - "Foos" (plural) is similar to the type name "Foo" (singular). But the resource name could be something else. It could be "GetFoos" or "GreatFoos" or anything at all. What matters is that the service method returns "Foo" entities.
Breeze needs a way to correlate the resource name with the EntityType
name. Breeze doesn't know the correlation on its own. The toType()
method is one way to tell Breeze about it.
toType()
?You generally don't add toType()
to your queries. Why now?
Most of the time [1], Breeze doesn't need to know the EntityType
until after the data arrive from the server. When the JSON query results includes the type name (as they do when they come from a Breeze Web API controller for example), Breeze can map the arriving JSON data into entities without our help ... assuming that these type names are in metadata.
When you query the cache ... say with executeQueryLocally
... Breeze must know which cached entity-set to search before it can query locally.
It "knows" if you specify the type with toType()
. But if you omit toType()
, Breeze has to make do with the query's resource name.
Breeze doesn't guess. Instead, it looks in an EntityType/ResourceName map for the entity-set that matches the query resource name.
The resource name refers to a service endpoint, not a cached entity-set. There is no entity-set named "Informacion", for example. So Breeze uses an EntityType/ResourceName map to find the entity type associated with the query resource name.
The EntityType/ResourceName map is one of the items in the Breeze MetadataStore
. You've probably never heard of it. That's good; you shouldn't have to think about it ... unless you do something unusual like define your own types.
The map of a new MetadataStore
starts empty. Breeze populates it from server metadata if those metadata contain EntityType/Resource mappings.
For example, the Breeze EFContextProvider
generates metadata with mappings derived from DbSet
names. When you define a Foo
class and exposed it from a DbContext
as a DbSet
named "Foos", the EFContextProvider
metadata generator adds a mapping from the "Foos" resource name to the Foo
entity type.
Controller developers tend to use DbSet
names for method names. The conventional Breeze Web API controller "Foo" query method looks like this:
[Get] public IQueryable<Foo> Foos() {...}
Now if you take a query such as this:
var query = EntityQuery.from('Foos').where(...);
and apply it to the cache
manager.query.executeLocally(query).then(...);
it just works.
Why? Because
DbSet
on the serverEFContextProvider
generated metadata mapping ["Foos" to Model.Foo
]Foos
action method.query
specifies "Foos"executeLocally
method finds the ["Foos"-to-Model.Foo
] mapping in metadata and applies the query to the entity-set for Foo
.The end-to-end conventions work silently in your favor.
... until you mention a resource name that is not in the EntityType/ResourceName map!
No problem!
You can add your own resource-to-entity-type mappings as follows:
var metadataStore = manager.metadataStore; var typeName = 'some-type-name'; var entityType = metadataStore.getEntityType(typeName); metadataStore.setEntityTypeForResourceName(resource, entityType);
Breeze is also happy with just the name of the type:
metadataStore.setEntityTypeForResourceName(resource, typeName);
In your case, somewhere near the top of your DataContext
, you could write:
var metadataStore = manager.metadataStore; // map two resource names to Esto metadataStore.setEntityTypeForResourceName('Esto', 'Esto'); metadataStore.setEntityTypeForResourceName('Informacion', 'Esto');
toType()
The toType()
method is a good short-cut solution when you need to map the top-level objects in the query result to an EntityType
. You don't have to mess around with registering resource names.
However, you must remember to add toType()
to every query that needs it. Configure Breeze metadata with the resource-to-entity-type mapping and you'll get the desired behavior every time.
[1] "Most of the time, Breeze doesn't need to know the EntityType
until after the data arrive from the server." One important exception - out of scope for this discussion - is when the query filter involves a Date/Time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With