问题
I have a breeze controller that adds an entity during the save changes that the client did not submit.
protected override bool BeforeSaveEntity(EntityInfo entityInfo)
{
if (entityInfo.Entity.GetType() == typeof(User))
{
if (entityInfo.EntityState == EntityState.Added)
{
User user = entityInfo.Entity as User;
OrganizationUser orgUser = new OrganizationUser()
{
Enabled = true,
OrganizationId = User.OrgId,
User = user
};
user.OrganizationUsers.Add(orgUser);
}
return true;
}
throw new InvalidOperationException("You can not use this service to modify an entity of type: " + entityInfo.Entity.GetType().Name);
}
When the response is returned the client side breeze manager sets the state of the server side added object as 'Added'. The OrganizationUser object above ends up with an Added state on the client. It then gets submitted in the next SaveChanges. Is this a bug?
Here is the response from the first save:
{
"$id": "1",
"$type": "Breeze.WebApi.SaveResult, Breeze.WebApi",
"Entities": [{
"$id": "2",
"$type": "LeonardoMD.Server.Api.Security.Admin.User, LeonardoMD.Server",
"Id": 9176,
"Email": "SearchProviderA@leonardoMD.com",
"FirstName": "SearchProviderA",
"LastName": "SearchProviderA",
"OrganizationUsers": [{
"$id": "3",
"$type": "LeonardoMD.Server.Api.Security.Admin.OrganizationUser, LeonardoMD.Server",
"UserId": 9176,
"User": { "$ref": "2" },
"OrganizationId": 421,
"Enabled": true
}]
}],
"KeyMappings": [{
"$id": "4",
"$type": "Breeze.WebApi.KeyMapping, Breeze.WebApi",
"EntityTypeName": "LeonardoMD.Server.Api.Security.Admin.User",
"TempValue": -1,
"RealValue": 9176
}]
}
Here is the submission of the second save:
{
"entities": [{
"Id": -2,
"CreateDate": null,
"CreateUserId": null,
"ModifyDate": null,
"ModifyUserId": null,
"Email": "SearchProviderB@leonardoMD.com",
"FirstName": "SearchProviderB",
"LastName": "SearchProviderB",
"BirthDate": null,
"GenderId": null,
"AddressLine1": null,
"AddressLine2": null,
"City": null,
"State": null,
"StateId": null,
"PostalCode": null,
"CountryId": null,
"DayPhone": null,
"DayPhoneExtension": null,
"Password": null,
"SecretQuestion": null,
"SecretAnswer": null,
"Enabled": null,
"AcceptTermsDate": null,
"entityAspect": {
"entityTypeName": "User:#LeonardoMD.Server.Api.Security.Admin",
"defaultResourceName": "Users",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": {
"propertyName": "Id",
"autoGeneratedKeyType": "Identity"
}
}
},
{
"UserId": 9176,
"OrganizationId": 421,
"Enabled": true,
"entityAspect": {
"entityTypeName": "OrganizationUser:#LeonardoMD.Server.Api.Security.Admin",
"defaultResourceName": "OrganizationUsers",
"entityState": "Added",
"originalValuesMap": {},
"autoGeneratedKey": null
}
}],
"saveOptions": {}
}
Notice the second entity is the entity returned in the response of the previous save changes. It's entityState is set to Added.
I have a work-around but its fragile and would need to be written special to every circumstance where the server returns a new entity after a save. Is there a way to set Breeze to acceptChanges on all new entities returned from the server as the the response to a saveChanges call?
manager.saveChanges()
.then(function (saveResult) {
$.each(saveResult.entities, function (i, entity) {
if (entity.organizationUsers && entity.organizationUsers().length > 0)
$.each(entity.organizationUsers(), function (index, orgUser) {
orgUser.entityAspect.acceptChanges();
});
entity.entityAspect.acceptChanges();
});
dfd.resolve();
})
.fail(function (error) { _this.handleError(context, promise, error); });
回答1:
We were able to reproduce the problem and it is a bug. (The entity added on server should have returned to the client as an Unchanged entity) We are working on a fix.
===EDIT===
The BeforeSaveEntity method is called once for each entity to be saved and should only manipulate the entity in question. You can find more about this at http://www.breezejs.com/documentation/custom-efcontextprovider.
If you want to create more entities to be saved in the server, you should do so in the BeforeSaveEntities method, where you can also add them to the saveMap dictionary to ensure they are saved in the DB.
i.e.
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) {
Dictionary<Type, List<EntityInfo>> saveMapAdditions = new Dictionary<Type, List<EntityInfo>>();
var prod = this.CreateEntityInfo(product, EntityState.Added);
// add data to the entity
saveMapAdditions[typeof(Product)].Add(prod);
return base.BeforeSaveEntities(saveMap);
}
回答2:
As of Breeze 1.3.5, available now, this has been fixed. and thanks for the repro...
来源:https://stackoverflow.com/questions/16838993/breezejs-server-added-object-showing-as-added-in-client-after-save-changes