I've got a many-to-many relationship mapped in my Entity Framework POCO classes. In the database it's a join table with a composite key, and the POCO properties are generated fine.
When I load an entity from the context, I can remove an item from the many-to-many collection and the database is updated when I save changes.
For Example:
var item = context.Items.First();
item.OtherItems.Remove(item.OtherItems[0]);
context.SaveChanges();
However, when the detached object graph comes back from WCF, I attach it to the context and mark it as modified. But the changes are not persisted.
Example:
// this happens on the silverlight client
item.OtherItems.Remove(item.OtherItems[0]);
// and on the server
context.Items.Attach(item);
context.ObjectStateManager.ChangeObjectState(item, EntityState.Modified);
context.SaveChanges();
In this case the record is not removed from the join table in the database. Any ideas how I can get this to work? Thanks very much in advance.
Changing object state marks your entity modified. You need to use ChangeRelationshipState to mark modified relation between two entities - this will perform DB modification on your join table. You will need to set relation's state as Added or Deleted.
Related
There is a ManyToOne association defined between entities Pattern and Category (Pattern is an owning side of the relation). Category has many patterns, pattern belongs to one category. So there is a field Pattern.category with #ManyToOne Doctrine annotation.
Now, in my scenario I have the id of the Category entity (posted from form) that I want assign to Pattern.category field of the newly created Pattern (which will be persisted), but I don't want to load this Category entity - I don't need it, I just want to create a Pattern entity, assign it to a Category (which id I have), and persist it. It seems strange to me, that I have to load the Category entity just to establish the connection, when all I really need is just an id, which I already have.
Maybe it smells like using relational database concepts with ORM, but it seems completely pointless to load this entity just to establish connection, when I know id of that target entity.
I am new to Doctrine btw.
You can use Reference Proxy:
$category = $em->getReference('Category', $id);
$pattern->setCategory($category);
I want to support cascade update of "truncated graphs" in NHibernate.
Say I have a Student entity and a Class entity which has a Students collection. The Students collection is mapped with "cascade all". Now, suppose that in the client only the a class entity was changed, so I want the client to be able to send only the class entity without the contained students. My approach is to let the client send the class entity with the Students property nullified and let the DAL understand that the Students collection should be ignored.
Unfortunately, when NHibernate gets null property class.Students when given to session.Merge, it disconnects the child students from the parent class by setting their FKs to null and/or deleting them (depending on the specific cascade option).
I would expect NHibernate to behave like that only when getting an empty collection and not when the collection is nullified.
Is there a way to workaround this? E.g. by telling NHibernate somehow to skip the nullified properties during merge?
You can set the inverse = "true" for the Student collection in the Class entity, so that it will not clear the FK.
Lets say I have entity A, which have many to many relationship with another entities of type A. So on entity A, I have collection of A. And lets say I have to "update" this relationships according to some external service - from time to time I receive notification that relations for certain entity has changed, and array of IDs of current related entities - some relations can be new, some existing, some of existing no longer there... How can I effectively update my database with EF ?
Some ideas:
eager load entity with its related entities, do foreach on collection of IDs from external service, and remove/add as needed. But this is not very effective - need to load possibly hundreds of related entities
clear current relations and insert new. But how ? Maybe perform delete by stored procedure, and then insert by "fake" objects
a.Related.Add(new A { Id = idFromArray })
but can this be done in transaction ? (call to stored procedure and then inserts done by SaveChanges)
or is there any 3rd way ?
Thanx.
Well, "from time to time" does not sound like a situation to think much about performance improvement (unless you mean "from millisecond to millisecond") :)
Anyway, the first approach is the correct idea to do this update without a stored procedure. And yes, you must load all old related entities because updating a many-to-many relationship goes only though EFs change detection. There is no exposed foreign key you could leverage to update the relations without having loaded the navigation properties.
An example how this might look in detail is here (fresh question from yesterday):
Selecting & Updating Many-To-Many in Entity Framework 4
(Only the last code snippet before the "Edit" section is relevant to your question and the Edit section itself.)
For your second solution you can wrap the whole operation into a manually created transaction:
using (var scope = new TransactionScope())
{
using (var context = new MyContext())
{
// ... Call Stored Procedure to delete relationships in link table
// ... Insert fake objects for new relationships
context.SaveChanges();
}
scope.Complete();
}
Ok, solution found. Of course, pure EF solution is the first one proposed in original question.
But, if performance matters, there IS a third way, the best one, although it is SQL server specific (afaik) - one procedure with table-valued parameter. All new related IDs goes in, and the stored procedure performs delete and inserts in transaction.
Look for the examples and performance comparison here (great article, i based my solution on it):
http://www.sommarskog.se/arrays-in-sql-2008.html
I am troubleshooting code that is attempting to update a disconnected entity that has uninitialized references to child entities. The intent is to update only the properties on Parent without loading children.
HasMany(x => x.ChildEntities)
.KeyColumn("ChildEntityId")
.Table("ChildEntity")
.Not.LazyLoad()
.Inverse()
.Cascade.All().AsBag();
When Session.Update(parent) is called, two update statements are executed. The first updates the parent object as expected.
update Parent set ... where ParentId = 12345
The second update confuses me...
update ChildEntity set ParentId = null where ParentId = 12345
Why is NHibernate issuing that second SQL statement? I realize that ChildEntities is uninitialized and that NHibernate is probably trying to enforce the state of Parent but I can't seem to tweak the mapping to not make this second update. I've tried Merge, lazy loading, various cascade options, etc. without success. The only connected entity in the session when it tries to commit is Parent.
Note that I typically approach this by retrieving the entity with lazy loading enabled and then mapping from the disconnected object (DTO or entity) to the connected entity before letting NHibernate persist to the database. I want to understand why the above isn't working before I suggest an alternative approach.
This was annoying.
A quick search through the NHibernate source for "could not delete collection" showed up in a block that could only execute if !isInverse (AbstractCollectionPersister.cs). That drew my attention because the mapping code was explicitly setting Inverse on that collection.
If Inverse is false and the collection is empty, NH executes an update on the child table setting the foreign key to null where the foreign key equals the parent id.
Fluent is configured to auto-map all entities in a given namespace. The assumption was that anything with a manual mapping would be ignored by auto mapping. A quick check of the hbm.xml files produced by Fluent confirmed that Inverse was not being set. I added Parent to the list of entities that were explicitly excluded from Auto Mapping and everything started working.
.IgnoreBase<Parent>()
I'm new to DDD and NHibernate.
In my current project, I have an entity Person, that contains a value object, let's say Address. Today, this is fine. But maybe one day I will have a requirement that my value object (in this case Address), will have to become an entity.
Before trying to model this on a DDD-way, in a more data-centric approach, I had a table Person, with an Id, and another table Address, whose PK was actually an FK, it was the Id of a Person (ie, a one-to-one relationship).
I've been reading that when I map a Value Object as a Component, its value will get mapped as columns on my Entity table (so, I would not have the one-to-one relationship).
My idea was that, when needed, I would simply add a surrogate key to my Address table, and then it becomes an Entity.
How should I design this using NHibernate? Should I already make my Address object an Entity?
Sorry, I don't even know if my questions are clear, I'm really lost here.
In the system we are building, we put Value-Objects in separate tables. As far as I know, NHibernate requires that an id must added to the object, but we ignore this and treat the object as a Value-Object in the system. As you probably know, a Value-Object is an object that you don't need to track, so we simply overlook the id in the object. This makes us freer to model the database the way we want and model the domain model the way we want.
You can Join and make it a Component allowing nHibernate to map it as a proper value object instead of an entity.
This way you won't need any virtual properties nor an empty protected ctor (it can be private).
Join("PROPOSAL_PRODUCT", product =>
{
product.Schema(IsaSchema.PROPOSALOWN);
product.KeyColumn("PROPOSAL_ID");
product.Component(Reveal.Member<Proposal, Product>("_product"), proposalProduct =>
{
proposalProduct.Map...
});
});