What is the reason of this error? My class is Course and it has notes. Mapping is as below. Any idea?
<bag name="Notes" table="NOTE" cascade="all">
<key column="COURSEID"/>
<one-to-many class="Server.Data.Note, Server.Data"/>
</bag>
<bag name="Notes" table="NOTE" cascade="all" inverse="true">
<key column="COURSEID"/>
<one-to-many class="Server.Data.Note, Server.Data"/>
</bag>
inverse="true" solves my problem :)
I my case the reason was that I was mapping a list to an abstract type (during a refactoring). When I changed the class from being abstract, it worked.
In my case the reason was that I converted an int to an enum (public enum FieldType : int { }).
Somehow, that convertion made an error jump where a Field had no Question. I made Question_id not nullable directly in the db, and removed the Fields with null question_id... and the error disappeared. (Replaced by another one, Can't parse 32 as int.. But still, improvement. I think the db type needs to be different.)
"Any sufficiently advanced technology is indistinguishable from magic."
Related
I'm getting some very strange behavior with Linq to nHibernate.
I can retrieve all objects I want and I can add where clauses.
But in a very specific case I get the following exception:
Could not load type x.Foo.Bar.Bars. Possible cause: the assembly was
not loaded or not specified.
x.Foo.Bar.Bars is part of a piece of lambda expression in a where clause.
Where Bars is a collection of objects. The collection get filled perfectly when I just query without the where clause.
query.Where(x => x.Foo.Bar.Bars.Any(b => b.Name == "BarName"));
The stacktrace is this:
at NHibernate.Util.ReflectHelper.ClassForFullName(String classFullName)
And yes, my mapping files are embedded resources.
Part of the mapping:
<bag name ="Bars" inverse="true" lazy="false"
cascade="none" optimistic-lock="false"
access="Framework.NHibernate.Properties.EntityCollectionAccessor, Assembly">
<key column="BagId" />
<one-to-many class="Bar"/>
</bag>
access="Bars, Assembly" looks wrong. You don't want to define an access strategy that is implemented in the class Bars, do you?
I have a PhoneBook class that has a list of PhoneNumber. Then I have another class "Account" that references PhoneNumber. This reference is nullable, so an account doesn't have to have a phone number.
I would like to be able to save the PhoneBook, have it save/update/delete all the phone numbers, AND if any of the phone numbers are deleted, I want to null out any accounts using this number. Everything is working except for the last part; if I delete a phone number that's in use it deletes the account too, which I do not want to happen, I just want it to clear it's reference. I'm sure it's just because my cascades or mappings are wrong, I just don't know what to set them to.
The actual code to save is relatively simple. Incidentally, if someone can tell me why I have to Merge in order to make sure phone numbers are deleted that would be awesome.
var session = SessionFactory.GetCurrentSession();
book = (PhoneBookDto) session.Merge(book);
session.SaveOrUpdate(book);
Current relevant mappings:
PhoneBook.hbm.xml
...
<bag cascade="all-delete-orphan" inverse="true" name="PhoneNumbers">
<key>
<column name="phone_book_id" />
</key>
<one-to-many class="DataLibrary.dto.PhoneNumberDto, DataLibrary" />
</bag>
...
PhoneNumber.hbm.xml
...
<many-to-one cascade="none" class="DataLibrary.dto.PhoneBookDto, DataLibrary" name="PhoneBook">
<column name="phone_book_id" />
</many-to-one>
...
Account.hbm.xml
...
<many-to-one cascade="none" class="DataLibrary.dto.PhoneNumberDto, DataLibrary" name="PhoneNumber">
<column name="phone_number_id" />
</many-to-one>
...
Thanks in advance!
edit:
Firo pointed me in the right direction, I had to set up a collection on PhoneNumber back to Account even though I don't really need it, and also set it as inverse=false:
<bag cascade="none" inverse="false" name="Accounts">
<key>
<column name="phone_number_id" />
</key>
<one-to-many class="DataLibrary.dto.AccountDto, DataLibrary" />
</bag>
When I did that, it worked. Is there any way to do this so I don't have to have an association on PhoneNumber to Account?
"why I have to Merge in order to make sure phone numbers are deleted":
Either because you removed Phonenumbers out of changetracking (closed session with which the book was loaded) or because there is no Flush at the end while merge will immediatly flush the SaveOrUpdate will only add to the batch which is executed on next session.Flush().
"it deletes the account too"
maybe because of:
<bag cascade="all" class="Account" name="Accounts">
</bag>
I am trying to develop my very first project with Nhibernate 3.0.
I've gone through loads of material (blogs, papers and samples) and I think I can understand the basics, pretty much.
I think I've understood the meaning of different types of collection but than when I see the examples found on the Internet I think I haven't really understood.
The documentation says that you should use a Set when you do not want duplicates and a List/Bag when you want to allow duplicates.
Most of the samples I have found are based on a typical situation where you have Orders/OrderLines.
If I have a look the mapping file of the Order I can see something like this:
<class name="OrderHeader"
table="Orders">
<id name="OrderId">
<generator class="hilo"/>
</id>
<property name="OrderDate"/>
<bag name="OrderItems" table="OrderDetails" cascade="all" inverse="true">
<key column="OrderId"/>
<one-to-many class="OrderDetail"/>
</bag>
</class>
<class name="OrderDetail"
table="OrderDetails">
<id name="DetailId">
<generator class="hilo"/>
</id>
<many-to-one name="ProductOrdered" column="ProductId"/>
<many-to-one name="Order" column="OrderId" />
</class>
I had expcted to see the OrderItems mapped as a Set; an order will have unique OrderItems?
Am I right?
At the same time I would expect to find a mapping for the class Product a bag of OrderItems
...
<bag lazy="true" name="OrderItems">
<key foreign-key="FK_OrderItems_Products">
<column name="ProductCode" />
</key>
.....
</bag>
...
In this situation a product would have a list of non-unique OrderItems.
Is there anything am I missing?
Forgive me all for the silly question :-s
I would set it as a <list ...> as in my book two orderlines with the same characteristics are identical (.Equals should return true) - also, many consider the order(!) of orderlines to be important. :-)
The reason for this is that bag mapping is compatible with a .NET IList<T> mapping as Yads answered. Collections are typically mapped that way to avoid having to reference Iesi.Collections in your classes.
With NHibernate 2.1, you can use set mapping by declaring the collection as ICollection<T> and initializing it as a HashSet<T>. Using NHibernate 3 I believe you can declare the collection as ISet<T>.
I agree most real world collections should be mapped as sets.
The reason most people implement it as a bag is because they can use the built in List<> class or IList<> interface to represent their collection.
Should a lazy loaded collection in NHibernate ever give me a NullReferenceException? I'm getting an exception in a method like the following:
public void Test(ISession session, int id)
{
var entity = session.Load<MyEntity>(id);
entity.LazyLoadedCollection.Add(SomeItem);
}
The call to LazyLoadedCollection is throwing. My mapping looks like:
<bag lazy="true" table="MyTable">
<key>
<column name="LazyLoadedCollection" />
</key>
<many-to-many class="LazyLoadedItem">
<column name="LazyLoadedItemId" />
</many-to-many>
</bag>
Is this the expected behavior in NHibernate?
It's hard to say without seeing your class, but one thing you may not have realized is that you need to populate each collection in your class's constructor.
NHibernate will replace these collections with its own at certain times, but you still need to make sure they're initially populated with a HashedSet<T>, List<T>, or something else depending on the interface you're using.
No it's not. This is a not a good way to ask a question on the internet.
And it's really impossible to give you a direction what to do if you don't post the code throwing the exception and tell us where the exception comes from.
I've asked this elsewhere and not got any sensible reply
I'm trying to map an IDictionary. I have this mapping:
<class name="MyProject.Item, MyProject" table="Item">
<...>
<map name="Properties" access="property" table="ItemProperties" lazy="false">
<key column="ItemID" />
<index column="Idx" type="int" />
<element column="Value" type="System.Boolean, mscorlib"/>
</map>
I can persist data, but when the data is retrieved I get an nHibernate exception:
{"The value "0" is not of type "Project.PropertyType" and cannot be used in this generic collection. Parameter name: key"}
So it can't map to the enum, but why ? if I have a regular property that uses an enum, it works fine.
Is what I'm trying to do even possible ? I can't find much info on doing this.
Your mapping shows the key as an integer, not as an enum. To map the enum properly, use type="MyProject.Project.PropertyType, MyProject".
However, normally for an enum the best approach is to leave the type information out of the mapping file altogether and let NHib pick it up through reflection. My reading of the NHib source implies that if you are mapping into a generic IDictionary<K,V> then NHib should pick up the exact type of your key via reflection. IOW you still should be able to leave out the type attribute.