I have some EF classes with properties that contain the DisplayName attribute. What would be the correct (if any) way to (dynamically) add this attribute in the breeze metadata so when I call manager.metadataStore.getEntityType(my_type) I can read it (like I can do with MaxLength? Or is this even possible?
You will need to create a method to reflect on your EF classes and extract the display name into the breeze 'Custom Metadata' json structure ( probably using JSON.NET to write the json on the server). You would then send this 'customMetadata' down to the client and call MetadataStore.importMetadata with it like this:
myEntityManager.metadataStore.importMetadata(customMetadata, true);
See the sections on Custom Metadata and Metadata by Hand
Related
I have to create and remove attributes based on an api response in Objective C.
For example, Now my api response contains fields "facebook", "whatsapp" and "viber". But in future the reponse can add "youtube". Based on this response, I have to remove all the attributes and values of an entity "Social", and create Four attributes now and set values.
How to do that programmatically? Because the default *.xcdatamodeld file cant help me here, right?
Note: My project is in objective C.
The data model is mutable when the app starts-- you can completely build the model in code, and not use the model editor, for example. But as soon as you load a persistent store file, you must treat the model as fixed. Any changes after loading a persistent store will cause crashes. That means any changes would have to happen before calling either loadPersistentStores(completionHandler:) or addPersistentStore(with:completionHandler:).
Alexander's suggestion of optional attributes is a good one. If you need the model to be more dynamic, you would need to create a new related entity which would store the service name plus whatever information you need to save about the service. If you did this, your Social entity would have a to-many relationship to a new entity called something like Service. Service would have a string property called name that would have values like twitter, facebook, youtube, etc. It would also have whatever other attributes you need to save about the service.
You can create all 4 fields in advance and just make them optional and fill them depending on the server response. But you cannot add new attributes in runtime. Your *.xcdatamodeld file compiles into *.momd and it contains all the data to create tables in the DB since Core Data by default works with SQLite under the hood and it's a relational database management system.
To make attributes optional you should check that.
And then newly created objects contain nil as default values of object properties. So, in your case your "youtube" property of Social object will be just nil.
I'm using breezejs with an entity framework 5 model. The model is the old-school edmx/objectcontext style- not the newer dbcontext/poco style.
The model is shared with some wcf ria services domain services so I cannot switch to entity framework 6 or poco style entity framework at this time.
When using wcf ria services, if you wanted to add a property to an entity beyond what is generated by entity framework you could create a partial class, define the property and annotate it with the datamember attribute. Wcf ria services treats this new property like any other property and sends it to the client from the server and back to the server.
Is there a way to do the same thing with breezejs? Without moving entirely away from the automatic metadata generation goodness that comes with using entity framework?
Using fiddler I can see the property I want exposed is transmitted to the client during a query request.
I've looked at the documentation here http://www.breezejs.com/documentation/extending-entities but none of the examples seem to fit this scenario.
Breeze supports unmapped properties, these are properties that are declared on your javascript constructor that cannot be matched to any property in metadata. By default these properties are both persisted locally and sent to the server on a save. This is described in the link you mentioned:
http://www.breezejs.com/documentation/extending-entities
var Customer = function () {
this.myUnmappedProperty = "anything22";
};
myEntityManager.metadataStore.registerEntityTypeCtor("Customer", Customer);
These values will be available on the server after a SaveChanges call via the 'UnmappedValuesMap' property on each EntityInfo instance.
var unmappedValue = entityInfo.UnmappedValuesMap["myUnmappedProperty"];
What is sounds like you are looking for is "unmapped" properties to go in the "other" direction, i.e. from the server to the client. What might work for that but we haven't tried is adding a property to your server side EF class ( via the partial class mechanism) and mark it up for Json serialization. It "should" then get serialized down to the client, even though it won't show up in Metadata.
If this does NOT work, please post back here and we will consider it as a breeze feature request. The basic idea does make a lot of sense and we should support it.
I'm trying to implement some custom model metadata in ASP.NET MVC 3. I can't use data annotation attributes since some of the metadata could change based on configured values, so I need a solution that will let me set the metadata on every request. I've been reading about custom model metadata providers, but I can't find anything about support for dynamic metadata scenarios.
Does the MVC framework cache the metadata from the model metadata provider, or will the CreateMetadata method be called on every request? Is a custom model metadata provider a good solution for dynamic metadata, or should I just put it in the view model?
Edit: This isn't necessarily validation metadata I'm talking about, so I'm not looking for a validation specific solution. It could just be metadata to be displayed or used by the view (in HTML 5 data attributes for example).
Another example might be a database driven field label. Usually one would use the Name property of the Display attribute, but this wouldn't work if you wanted to dynamically set the display name based on a value in the database.
You can derive your custom provider from DataAnnotationsModelMetadataProvider so you will inherit all the base behaviour.
Yes, CreateMetadata is called on every request, so you can do something fancy, like go to DB and load some data that may change in time.
For labels I would implement custom ResourceProvider that uses Db as the source of label (based on current culture / account, etc.) Example is here: http://www.codeproject.com/Articles/14190/ASP-NET-2-0-Custom-SQL-Server-ResourceProvider
I'm trying to update a backbone model, the server side is asp.net mvc 4. I'm getting:
"System.ArgumentException: An item with the same key has already been added" exception.
The reason is because backbone is sending Id and id to the server as properties, and the JsonValueProvider tries to add this to a dictionary.
Here is my model:
var Task = Backbone.Model.extend({
url: "/tasks/task",
idAttribute: "Id"
});
This is send to the server via Put request:
{"Id":294912,"Task":"test","DueDate":"2012-03-24T02:00:00.000Z", "id":294912}
Is there a way to prevent backbone in sending the "id" property?
The problem here is because the conventions in C# is not the same as in JavaScript. In C# classes have properties that starts with capital letters (Pascal Case) and it's the norm in JavaScript to start your properties in lower case (Camel Case).
Thus when serializing view models the default behavior of the JSON.NET serializer is to serialize the object exactly with the same capitalization of properties. I could rename the properties on the view model to be camel case, but it would be as "weird" as to have properties with pascal case in your JavaScript objects.
So instead to force Backbone into a non convention way, I've change the serialization of the objects to convert the Pascal case properties into Camel case properties by leveraging JSON.NET's Contract Resolver functionality.
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
JsonSerializer serializer = JsonSerializer.Create(settings);
JsonConvert.SerializeObject(object, Formatting.None, settings);
Now this creates consistency on the client side with my code and with all the cool libraries out there.
Sounds to me like the issue is in your server-side code, not with the call from Backbone. A PUT is an edit operation on the server, so you're updating an existing entity. You need the ID property to identify the model on the server and update the properties that have changed.
If ASP.NET MVC is complaining that the model already exists in the database, you are trying to do an INSERT instead of an UPDATE. We'd need to see the controller and data access code to see where things are going awry.
UPDATE: What happens if you leave off the idAttribute property? From the Backbone documentation:
A special property of models, the id is an arbitrary string (integer id or UUID).
If you set the id in the attributes hash, it will be copied onto the model as a
direct property.
The id attribute should be sent by default; it looks like you're forcing it to be included a second time.
Under idAttribute in the docs:
A model's unique identifier is stored under the id attribute. If you're directly communicating
with a backend (CouchDB, MongoDB) that uses a different unique key, you may set a Model's
idAttribute to transparently map from that key to id.
ASP.NET MVC's model binding should be able to cope with id vs. Id.
UPDATE: Found a good blog post that describes using a view model to aid in serializing your C# objects into the format Backbone expects. This seems like a reasonable, if slightly annoying, solution.
I have an entity/table that uses sqlgeography.
Since EF 4.X doesn't support spatial types I'm instead sending the bytes of the field back and forth.
I have stored procs on the database side that handles the converstion and properties on the code side to do that job.
To add the properties in the code I used a partial class.
One of those properties is for the SqlGeography which simply wraps around the byte[] property to handle getting and setting.
This property is hidden from EF using the NotMappedAttribute.
The other is the property exposing the byte[] itself and is decorated with the EdmScalarPropertyAttribute and DataMemberAttribute.
I then go to the EF model designer (*.edmx) to point the entity model at the Insert/Update/Delete stored procs.
It finds the stored procs alright and realises that they (when appropriate) take a VARBINARY parameter.
It also has a drop down allowing you to select a property on the entity class which maps to that parameter.
However this drop down doesn't list either of my properties. I don't care about the SqlGeography property since that is meant to be hidden from EF, however it is vital for me to be able to point it at the byte[] property, as that is where the data comes from.
I would very much like to avoid database triggers or wrapper classes and addiitonal fields to fudge this in to working.
I tried manually editing the .edmx file to include the byte[] property, but then it just complains it's unmapped.
Can anyone give me some insight in to how to get this to work? Or an alternative method of achiving the end result?
We could use a view to create the binary field for us, but this then involves manually creating a lot of the xml for the relationships within the data.
This pretty much voids the point of using EF which is to make life simple and easy.
For this project We'll just add a binary field to the table then have sprocs to handle the converstion on the server and a property in a partial entity class for exposing the geography type in the model.
Next project I doubt we'll be using EF. Dapper is so much more painless, even if theres a touch more code writing involved.
Here's the links for using views if anyone thinks it would be applicable to them:
http://thedatafarm.com/blog/data-access/yes-you-can-read-and-probably-write-spatial-data-with-entity-framework/
http://smehrozalam.wordpress.com/2009/08/12/entity-framework-creating-a-model-using-views-instead-of-tables/
In the end we created a computed column for each table that exposes the spatial data as bytes.
We then use stored procs for inserting and updating the spatial data.