Background:
I'm using the SandboxManager format described in the documentation to export my entities to a second manager for changes, and then the entity is imported back into the main manager. I'm creating the Sandbox on page initialization from a copy of the main manger using createEmptyCopy(), giving the Sandbox the same metadata and no entities.
During the export, I pass the entity over this way:
function exportEntityToSandbox(entity) {
var exportData = STEP.EntityManager.exportEntities([entity], false);
var result = STEP.SandboxManager.importEntities(exportData,
{ mergeStrategy: breeze.MergeStrategy.OverwriteChanges });
// ImportEntities changes the service name so revert it back
STEP.SandboxManager.setProperties({
dataService: new breeze.DataService({
serviceName: 'api/Sandbox',
hasServerMetadata: false
})
});
return result.entities[0];
};
I'm currently working with this entity:
public class License
{
public int ID { get; set; }
public int LicenseTypeID { get; set; }
public virtual LicenseType LicenseType { get; set; }
public int ExternalProductID { get; set; }
public virtual ExternalProduct ExternalProduct { get; set; }
public int? LicensesPurchased { get; set; }
public int? LicensesAllocated { get; set; }
public string AllocationDescription { get; set; }
public bool DeletedFlag { get; set; }
}
And the map for this entity:
public LicenseMap()
{
this.HasKey(t => t.ID);
this.Property(t => t.ID)
.HasColumnName("ID")
.HasColumnType("int")
.IsRequired();
this.Property(t => t.LicenseTypeID)
.HasColumnName("LICENSE_TYPE_ID")
.HasColumnType("int")
.IsRequired();
this.Property(t => t.ExternalProductID)
.HasColumnName("PRODUCT_ID")
.HasColumnType("int")
.IsRequired();
this.Property(t => t.LicensesPurchased)
.HasColumnName("LICENSES_PURCHASED")
.HasColumnType("int")
.IsOptional();
this.Property(t => t.LicensesAllocated)
.HasColumnName("LICENSES_ALLOCATED")
.HasColumnType("int")
.IsOptional();
this.Property(t => t.AllocationDescription)
.HasColumnName("ALLOCATION_DESCRIPTION")
.HasColumnType("varchar")
.HasMaxLength(Int32.MaxValue)
.IsOptional();
this.Property(t => t.DeletedFlag)
.HasColumnName("DELETED_FLAG")
.HasColumnType("bit")
.IsRequired();
this.ToTable("LICENSE");
}
}
I'm only passing in the License entity during export--the ExternalProduct and LicenseType navigation entities are not passed to the Sandbox. However, ALL ExternalProducts & LicenseTypes are loaded into the Main manager on page initialization. So in the workflow, I select from a list of dropdowns the ExternalProduct and update ONLY the ExternalProductId (as the ExternalProduct itself is not on the Sandbox).
Issue:
The problem I'm facing is when the entity is exported back into the Main Manager:
function save(id, manager, tag) {
manager = manager || STEP.SandboxManager;
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(data) {
var exportData = STEP.SandboxManager.exportEntities(data.entities, false);
STEP.EntityManager.importEntities(exportData,
{ mergeStrategy: breeze.MergeStrategy.OverwriteChanges });
// ImportEntities changes the service name
// Revert it back
STEP.EntityManager.setProperties({
dataService: new breeze.DataService({
serviceName: 'api/Datamart',
hasServerMetadata: false
})
});
// Get a reference to the same entity in the Sandbox and update observable
var entityKey = data.entities[0].entityAspect.getKey();
var type = entityKey.entityType.shortName;
var entityManagerEntity = STEP.EntityManager.getEntityByKey(type, id);
};
function saveFailed(msg) {
// Do stuff
};
};
The entity has a new ExternalProductId (changed during edit), but still has the old ExternalProduct navigation entity. The new navigation entity is not wired up to License even though I know it's in the cache. The navigation property still points to the old entity (property License.ExternalProductId does not equal License.ExternalProduct.ID).
So am I expecting too much of Breeze to do this rewiring upon import and I will need to do this manually every time?
I thought this may a problem with my EF definition and have tried adding each of these to the LicenseMap with no success:
this.HasRequired(m => m.ExternalProduct)
.WithOptional()
.Map(m => m.MapKey("ExternalProductID"));
this.HasRequired(t => t.ExternalProduct
.WithMany()
.HasForeignKey(t => t.ExternalProductID)
.WillCascadeOnDelete(false);
This is a required relationship with the navigation property on the License entity only. I'm using Breeze v1.4.11
Edit:
I just made sure this was in the entity map:
this.HasRequired(t => t.ExternalProduct)
.WithMany()
.HasForeignKey(t => t.ExternalProductID);
And tested this simple coding snippet:
license.ExternalProductID(816);
var test = license.ExternalProduct();
And the test variable of navigation entity ExternalProduct still does not change after setting the ID directly. According to Breeze documentation the navigation entity should be updated unless I'm doing something wrong?