1
votes

Say I have a movie entity, with an average score. A user can rate a movie, and for that I call datacontext.savechanges on the client, sending a Rating object to the server. On the server, the SaveChanges method is called, and in the BeforeSaveEntity method, I adapt the movie's average score.

Here's the question: how to return that average score from the server's SaveChanges method, for example inside the SaveResult object?

I thought I could add the movie entity to the SaveResult Entities list, but then: - I would need to access attributes from within the saveBundle parameter - I would have to requery the DB, which I just did in BeforeSaveEntity

Thanks

Nicolas

2
Update the score in the BeforeSaveEntities method. Be sure to include the entity holding the score property to the save map. - pawel
Yes I should be able to do that, but get a "Sequence contains no matching element" error. - Nicolas
Some code would help me understand the question better. Don't forget that you can override the SaveChangesCore which may afford some opportunities to tweak things. And then you have another opportunity again before the Web API returns the SaveResult (you could have squirreled away a value somewhere for use in your controller). Finally, there is nothing sacred about the SaveResult per se. From the client perspective it's a structural type: anything that serializes the expected stuff will be accepted by the BreezeJS EntityManager. Lots of options. - Ward
Interesting! But, the method you mention (SaveChangesCore) is nowhere to be found in the documentation. (breezejs.com/documentation/custom-efcontextprovider) Only mentioned in the NoDB sample, which I had not read since.. I use a DB :). Anyway, in the meantime I actually used a workaround and and store the values I need in System.Web.HttpContext.Current.Items. - Nicolas

2 Answers

1
votes

As pawel pointed out in the comments: To return the movie in the SaveChanges promise, update the movie in your BeforeSaveEntities method on your custom EFContextProvider and add it to the saveMap.

I've put together some code for you.

protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type,   List<EntityInfo>> saveMap) {
    Movie movie = null;
    // initialize the movie variable and update the movie as needed
    saveMap.Add(typeof(Movie), movie);

    return saveMap;
  }
1
votes

Yes, it is possible.

Write your controller against an EDMX as you would do normally do. For us, it translates into something like this:

public class PersonalizationController : MultiTenantBreezeController<PersonalizationEntities>

where the PersonalizationEntities is an ObjectContext.

Then on the server, we simply define the SaveChanges (do not mind the override, we do have a base class)

[HttpPost]
public override SaveResult SaveChanges(JObject saveBundle)
{
     // Deserialize the object that needs to get saved (ApplicationDefaults is my DTO)
     var applicationDefaultsList = JsonConvert.DeserializeObject<List<ApplicationDefaults>>(saveBundle.SelectToken("entities").ToString());

     // Do whatever logic you need to save the data
     using (var repo = ServiceLocator.Current.Container.Resolve<IUserPreferenceRepository>())
     {
          // Your save logic here
     }

     // Construct the save result to inform the client that the server has completed the save operation
     var keyMappings = new List<KeyMapping>();
     return new SaveResult()
     {
         Entities = applicationDefaultsList.Cast<object>().ToList(),
         Errors = null,
         KeyMappings = keyMappings
     };
}