| Author |
Share Topic Topic Search Topic Options
|
bennage
Newbie
Joined: 04-Aug-2010
Location: Tallahassee, FL
Posts: 9
|
Post Options
Quote Reply
Topic: Value is not compatible with property Posted: 04-Aug-2010 at 9:00am |
|
I have 3 entities of interest. Something like this:
Order
LineItem
Product
Order can have many LineItems, a LineItem can have a single Product.
Everything has integer ids.
I retrieve an instance of an existing Order.
I create a new LineItem and associate it with an existing Product.
I then add the new LineItem to a collection of LineItems on the Order instance. I get the exception below.
The exception occurs as a add the LineItem. For example, on:
order.LineItems.Add( new LineItem() { Product = product };
Prior to adding , the LineItem has an id of -100 (or -101 or something similar).
Value is not compatible with property: Id DataType: System.Int32
at IdeaBlade.EntityModel.EntityWrapper.CheckPropertyValueCompatibility(DataEntityProperty property, Object newValue)
at IdeaBlade.EntityModel.EntityWrapper.SetValueWithChangeNotification(DataEntityProperty property, Object newValue)
at IdeaBlade.EntityModel.EntityWrapper.SetValue(DataEntityProperty targetProperty, EntityWrapper sourceEntity, DataEntityProperty sourceProperty)
at IdeaBlade.EntityModel.ScalarEntityReference`1.UpdateOtherProperties(EntityRelationLink relationLink, EntityWrapper fromEntity, EntityWrapper toEntity)
at IdeaBlade.EntityModel.ScalarEntityReference`1.UpdateFkForNewToEntity(EntityWrapper toEntity)
at IdeaBlade.EntityModel.ScalarEntityReference`1.SetEntity(T newValue, Boolean updateFkValues, Boolean updateInverseValues)
at IdeaBlade.EntityModel.ScalarEntityReference`1.AddEntity(Object entity, Boolean updateInverseValues)
at IdeaBlade.EntityModel.RelatedEntityList`1.AddInverse(T otherEntity)
at IdeaBlade.EntityModel.RelatedEntityList`1.AddOrInsert(Int32 index, T item, Boolean updateInverse)
at IdeaBlade.EntityModel.RelatedEntityList`1.Add(T item)
at MSU.CollegeOfMusic.MVC.Controllers.AdmissionApplicationController.AddInstitution(InstitutionOfInterestViewModel vm, Int32 applicationId) in E:\projects\msu\src\MSU.CollegeOfMusic.MVC\Controllers\AdmissionApplicationController.cs:line 75
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
|
 |
bennage
Newbie
Joined: 04-Aug-2010
Location: Tallahassee, FL
Posts: 9
|
Post Options
Quote Reply
Posted: 04-Aug-2010 at 10:41am |
|
I should add, this is 6.0.4, in the context of an ASP.NET MVC application.
|
 |
WardBell
IdeaBlade
Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
|
Post Options
Quote Reply
Posted: 04-Aug-2010 at 11:47am |
Hi Christoper -
Hmm ... that sure is raw
order.LineItems.Add( new LineItem() { Product = product };
I'm sure this is demo code :-)
I don't know the answer because I don't have the code. But 'm going to interpret the call stack with you and see if that is suggestive.
It seems you survived the creation of the LineItem and the assignment of its Product.
DevForce is in the process of adding the line item to the list. Having realized the direction of the relationship, it knows it must update the Order FK value of the LineItem
...AddInverse(T otherEntity)
...SetEntity(T newValue, Boolean updateFkValues, Boolean updateInverseValues)
Now it must ensure that the Order FK property type (LineItem.OrderId ?) is compatible with the type of the Order' primary key type (Order.Id).
...CheckPropertyValueCompatibility(DataEntityProperty property, Object newValue)
And apparently the two property types are "incompatible"
Value is not compatible with property: Id DataType: System.Int32
This makes me wonder if the Order.Id and LineItem.OrderId are both Int32. Maybe they are both integer types but not both Int32. Of course then I'd have to wonder (a) how you got this far without DevForce objecting earlier and (b) why we don't coerce if we can. But let's see what you find out first.
|
 |
bennage
Newbie
Joined: 04-Aug-2010
Location: Tallahassee, FL
Posts: 9
|
Post Options
Quote Reply
Posted: 04-Aug-2010 at 12:18pm |
|
It turns out the "Value is not compatible with property" was something of a red herring.
My problem was that I was trying to load an Order that didn't exist (id = 0). When I corrected this (so that I was actually loading a real order) this particular error when away.
I'm now experiencing another exception. I'll report back once it is fixed.
|
 |
bennage
Newbie
Joined: 04-Aug-2010
Location: Tallahassee, FL
Posts: 9
|
Post Options
Quote Reply
Posted: 04-Aug-2010 at 12:41pm |
|
Ok, here's my new exception (though perhaps this should be a new post).
When I call SaveChanges() on the manager after adding the LineItem. I get this exception:
IdGenerator problem - not all temp ids converted to permanent ids.
If you are using auto-incrementing ids check that the FixupTempIds SaveOption is set to InSaveListOnly.
This may also occur if your custom IIdGenerator was not found or its GetRealIdMap method did not
provide a corresponding real id for each temp id.
|
 |
bennage
Newbie
Joined: 04-Aug-2010
Location: Tallahassee, FL
Posts: 9
|
Post Options
Quote Reply
Posted: 04-Aug-2010 at 12:43pm |
|
The LineItem is assigned an id (usually 33), I'm not certain where this id comes from.
|
 |
WardBell
IdeaBlade
Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
|
Post Options
Quote Reply
Posted: 05-Aug-2010 at 1:02am |
Something is unexpected and unexplained about your model and your application. I cannot reproduce these behaviors using the NorthwindIB tutorial database and the usual out-of-the-box, table-per-type mapping.
Below is my test ... which passes. Because it passes and the wheels come off for you ... even if you later thought you got it to work ... suggests that you have an unusual, possibly corrupt model or that there are steps in the process that are unknown to me. The fact that you have Order.Id == 0 instead of a negative number (indicating a temporary id) indicates another missing piece to the story. I don't suppose you wrote your own custom IdGenerator ... that would be a pertinent fact.
The SaveChanges misbehaviors aren't reproducable in my setup either ... which is unsurprising given that I don't have your model or code.
I'll need a cutdown version of the model, the edmx, and your code to make progress. Sorry about that.
Here's my test. Note that I never bother to talk to the database; I can test the pertinent facts without going near a database.
[TestMethod] public void can_add_lineItem_to_new_detached_order() { var mgr = new NorthwindManager(false /* = disconnected */); // Pretend we retrieved an existing product var prod = new Product { ProductID = 42, ProductName = "Foo", }; mgr.AttachEntity(prod); // attaches as "unchanged"
var order = new Order(); // not yet associated with a manager // Create new lineitem which is immediately added to mgr // because the assignment of its Product pulls it into // the mgr of the "Prod" entity. // The act of adding this lineitem to the lineitems of the order // causes the new order to be pulled into the mgr as well.
// All this confirmed in subsequent Asserts. order.OrderDetails.Add(new OrderDetail{Product = prod}); Assert.AreEqual(order.EntityAspect.EntityState, EntityState.Added); Assert.AreEqual(1, order.OrderDetails.Count);
var lineItem = order.OrderDetails.First(); // get the new OrderDetail
Assert.AreEqual(lineItem.EntityAspect.EntityState, EntityState.Added); Assert.AreSame(lineItem.Product, prod); Assert.AreSame(order.EntityAspect.EntityManager, lineItem.EntityAspect.EntityManager); Assert.AreSame(order.EntityAspect.EntityManager, prod.EntityAspect.EntityManager); }
Edited by WardBell - 05-Aug-2010 at 1:05am
|
 |
WardBell
IdeaBlade
Joined: 31-Mar-2009
Location: Emeryville, CA,
Posts: 338
|
Post Options
Quote Reply
Posted: 05-Aug-2010 at 1:36am |
A pal of mine offered some additional thoughts:
First look at the DebugLog to see if an IdGenerator is being discovered – if not – bingo
If so, have him send the IdGenerator that he is using., or have him debug into his IdGenerator GetRealIdMap method.
Or
He may be using autoincrement ids and only sending part of the graph – hence the hint about
If you are using auto-incrementing ids check that the FixupTempIds SaveOption is set to InSaveListOnly
And how could you be "only sending part of the graph"? You would be doing so if you called
manager.SaveChanges(someEntities)
where "someEntities" is a subset of the entities you changed.
I'm always wary of this overload. It's too easy to omit an entity that has changes and should have been saved with the others. The mistake can mean a data integrity problem.
That overload has its place ... but one needs to be certain.
You might ask "what is that 'FixupTempIds SaveOption'?". The DevForce "API Reference" is a good place to learn about it (that's the help file generated from our XML comments; find it from Windows Menu | All Programs | DevForce 2010 ... | Documentation).
Turns out you can tune the SaveChanges behavior with a SaveOptions object. SaveOptions has several properties, one of which is FixupTempIds. Its "InSaveListOnly" enum means "Perform Id fixup only on those entities passed into the SaveChanges method. "
Looking at the debug log is ALWAYS a good first step when you're wondering what the server did. If we ask you to send us an example of a problem, we'll want that debug log too.
|
 |
bennage
Newbie
Joined: 04-Aug-2010
Location: Tallahassee, FL
Posts: 9
|
Post Options
Quote Reply
Posted: 05-Aug-2010 at 7:42am |
|
I'll send you a sample project for review.
|
 |
Matt Foley
Newbie
Joined: 21-Jul-2011
Location: Birmingham, AL
Posts: 9
|
Post Options
Quote Reply
Posted: 21-Jul-2011 at 9:58am |
I am having the same issue as your second issue, IdGenerator problem - not all temp ids converted to permanent ids. If you are using auto-incrementing ids check that the FixupTempIds SaveOption is set to InSaveListOnly. This may also occur if your custom IIdGenerator was not found or its GetRealIdMap method did not provide a corresponding real id for each temp id.
However this occurs for me after a EntityManager.RejectChanges(); call. I have a similar model structure in that I am creating an entity with subentities that are automatically filled with auto-generated int id's on a Create method in the entity's partial class definition. I have tried the suggestion of specifying the FixupTempIds SaveOption to InSaveListOnly by modifying the Manager's DefaultSaveOptions (because I have no way to pass it in as a param since this is happening in RejectChanges). Also, saving has no problems.
|
 |