fluent nhibernate, unable to resolve property: <property> - fluent-nhibernate

I have a one-to-one relationship in my db and I seem to be having issues with my fluent nhibernate mapping of this relationship.
When I attempt to insert a new TableA entity I receive the following error: "unable to resolve property: TableA". The error is thrown on this line in the repository: int id = (int)_session.Save(item);
Repository code:
public T Save(T item)
{
try
{
_session.BeginTransaction();
int id = (int)_session.Save(item);
_session.Transaction.Commit();
return _session.Get<T>(id);
}
catch (Exception)
{
_session.Transaction.Rollback();
throw;
}
}
Table definitions:
Table A
Id (int, pk, identity)
Field1 (nvarchar)
Field2 (date)
...
Table B
TableAId (int, pk) <-- no fk constraint on these tables
Field1 (nvarchar)
Field2 (nvarchar)
Field3 (bit)
Classes:
public class TableA
{
public virtual int Id {get;set;}
public virtual string Field1 {get;set;}
public virtual DateTime Field2 {get;set;}
public virtual TableB TableB {get;set;}
}
public class TableB
{
public virtual int TableAId {get;set;}
public virtual string Field1 {get;set;}
public virtual string Field2 {get;set;}
}
Mapping:
public class TableAMap : ClassMap<TableA>
{
public TableAMap(){
Id(x => x.Id);
Map(x => x.Field1);
Map(x => x.Field2);
HasOne(x => x.TableB)
.Cascade.SaveUpdate()
.Fetch.Join();
}
}
public class TableBMap : ClassMap<TableB>
{
public TableBMap()
{
Id(x => x.Id, "TableAId").GeneratedBy.Foreign("TableA");
Map(x => x.Field1);
Map(x => x.Field2);
Map(x => x.Field3);
}
}
I used these as a reference:
http://avinashsing.sunkur.com/2011/09/29/how-to-do-a-one-to-one-mapping-in-fluent-nhibernate/
One-to-one Mapping issue with NHibernate/Fluent: Foreign Key not updateing
IndexOutOfRangeException Deep in the bowels of NHibernate
I've been looking at this for so long now I fear I'm missing something simple (and stupid).
Update:
Tried this:
public class TableA
{
public virtual int Id {get;set;}
public virtual string Field1 {get;set;}
public virtual DateTime Field2 {get;set;}
public virtual TableB TableB {get;set;}
public virtual int TableBId
{
get{return TableB.Id;}
set{}
}
}
public class TableAMap : ClassMap<TableA>
{
public TableAMap()
{
Id(x => x.Id);
Map(x => x.Field1);
Map(x => x.Field2);
HasOne<TableB>(x => x.TableB)
.Cascade.SaveUpdate()
.Fetch.Join()
.ForeignKey("TableBId");
}
}
public class TableBMap : ClassMap<TableB>
{
public TableBMap()
{
Id(x => x.Id, "TableAId");
Map(x => x.Field1);
Map(x => x.Field2);
Map(x => x.Field3);
}
}
I didn't get the "unable to resolve property: TableA" error this time, but I received a different error. It seems like the Id of the TableA record did not cascade to the TableB record.
Did some more reading.
Found this post: fluent NHibernate one-to-one relationship?
Made some more changes:
public class TableAMap : ClassMap<TableA>
{
public TableAMap()
{
Id(x => x.Id);
Map(x => x.Field1);
Map(x => x.Field2);
HasOne<TableB>(x => x.TableB)
.Cascade.All()
.Constrained()
.Fetch.Join()
.ForeignKey("TableBId");
}
}
public class TableBMap : ClassMap<TableB>
{
public TableBMap()
{
Id(x => x.Id, "TableAId").UnsavedValue(0).GeneratedBy.Foreign("TableA");
Map(x => x.Field1);
Map(x => x.Field2);
Map(x => x.Field3);
HasOne<TableA>(x => x.TableA);
}
}
New error:
"attempted to assign id from null one-to-one property: TableA"

Even though this relationship is a one-to-one, and should be a one-to-one, I ended up modifying my database defintion to make this relationship a many-to-one and I mapped it as a many-to-one. Now it works. I'm not happy about it though, I think there should be a way to successfully map a one-to-one.
I was wasting too much time trying to get the one-to-one mapping to work and for the sake of my timeline I just needed to move on.

Related

NHibernate: Persisting subclassed entity to main table (table per class strategy issue)

It is not a question but just for future... (spent many time to figure out)
public class A
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
public class B : A
{
public string Lastname { get; set; }
}
Mappings (Fluent NHibernate):
public class AMap : ClassMap<A>
{
Table("a");
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Name);
Map(x => x.Type);
DiscriminateSubClassesOnColumn<string>("Type")
.AlwaysSelectWithValue();
}
public class BMap : ClassMap<B>
{
DiscriminatorValue("BType");
Extends<A>();
Map(x => x.Lastname);
}
Persisting BMap object leads to Exception:
Exception:
Error dehydrating property value for A.Lastname
Inner Exception:
Invalid index 1 for this SqlParameterCollection with Count=1
This unobvious exceptions tell that some mapping missconfiguration occured. Actually "select" queries work pretty fine. But "insert into" (ISession.SaveOrUpdate) causes mentioned errors.
FIX:
In AMap class you don't need that line:
Map(x => x.Type);
After removing this persister works fine
type does not need to be in the class nor mapped as property, it is purly implementation detail in the database to discriminate the types. Instead of Extends SubclassMap is more appropriate:
public class AMap : ClassMap<A>
{
Table("A");
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.Name);
DiscriminateSubClassesOnColumn<string>("Type", "AType")
.AlwaysSelectWithValue();
}
public class BMap : SubclassMap<B>
{
DiscriminatorValue("BType");
Map(x => x.Lastname);
}

fluent NHibernate: many-to-many relationship with Product to Product

fluent NHibernate: many-to-many relationship with Product to Product.how i can implement it on asp.net mvc
public class Product
{
public virtual int Id { get; set; }
public virtual IList<Product> ManyProduct { get; set; }
}
Mapping
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.Id);
Map(x => x.ImageUrl);
}
HasManyToMany(x => x.ManyProduct)
.Cascade.All()
.Table("ProductInProduct");
}
You don't specifically say what is wrong but your HasManyToMany definition needs to specify the Parent and Child Id columns from your ProductInProduct table:
HasManyToMany(x => x.ManyProduct)
.Table("ProductInProduct")
.ParentKeyColumn("ParentId")
.ChildKeyColumn("ChildId")
.Cascade.All();

"Tried to add property 'Id' when already added."-Error when implementing own class twice

I would like to have a mapped class named "Message". This class should include an unique id, the title, the text, and information about the sender and the receiver. I need their User-ID an their name, so I've created another class named "User". This class include these two properties (later I'll create some methods for this class and use it in different classes, so I can not use onyl the class "Message").
This is my code
public class User
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
public class Message
{
public virtual Guid Id { get; set; }
public User sender;
public User receiver;
public virtual string subject { get; set; }
public virtual string text { get; set; }
}
public class MessageMap : ClassMap<Message>, IMappedEntity
{
public MessageMap()
{
Id(x => x.Id, "MessageId");
Map(x => x.sender.Id, "SenderId");
Map(x => x.receiver.Id, "ReceiverId");
Map(x => x.subject);
Map(x => x.text);
}
}
As you can see, I want to save only the User-ID of the sender and receiver, not their names. Because x.Id, x.sender.Id and x.receiver.Id have the property "Id", I wrote down a spezific name for them in the database.
But if I try to load the site, this error appears: Tried to add property 'Id' when already added., even if their is no more property named "Id" after I definited the Name for the columns...
Could you give me a hint what I'm doing wrong?
I finally found an other solution: I changed the mapping of my Message-Map to this:
public class MessageMap : ClassMap<Message>, IMappedEntity
{
public MessageMap()
{
Id(x => x.Id);
Component(
x => x.sender,
userId =>
{
userId.Map(x => x.Id, "senderId");
}
);
Component(
x => x.receiver,
userId =>
{
userId.Map(x => x.Id, "receiverId");
}
);
Map(x => x.subject);
Map(x => x.text);
}
Now, I do not have to map the User-Class, so I don't have a table only with my Userids.
I'm not too familar with using nHibernate, so I'm not shure wether this is the best way to solve the problem, but in my eyes this fits a bit more to my problem then the solution presented by Chev (but I'm very grateful that you have answered me!)
Change the MessageMap as follows.
public class MessageMap : ClassMap<Message>, IMappedEntity
{
public MessageMap()
{
Id(x => x.Id);
References(x => x.Sender);
References(x => x.Receiver);
Map(x => x.subject);
Map(x => x.text);
}
}

Fluent Nhibernate: Mapping Issue

I am very much new to Fluent Nhibernate. I am stuck with the one situation.
Please find bellow details about it.
Our table structure is like as
Table Student { Student_Id, Name}
Table School { School_Id, Name}
Table LinkTable { School_Id, Student_Id}
LinkTable contains only id of the Student and School. [Composite Key]
Relation is like
1) One student can be part of 0 or 1 School.
2) One School can contains many students.
Can anyone please let me know how the mapping will be done for each file?
or let mw know what is wrong in following mapping files
Right now, it is giving me error that Student Property is not found on SchoolStudent.
public Student()
{
Id(x => x.Id);
Map(x => x.Name);
HasOne(x => x.SchoolStudent).PropertyRef(r => r.Student);
}
public School()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.SchoolStudent).KeyColumn("School_Id").Inverse().Cascade.AllDeleteOrphan();
}
public SchoolStudent()
{
CompositeId().KeyReference(x => x.School, "School_Id")
.KeyReference(x => x.Student, "Student_Id");
}
Thanks,
Mahesh
I would re-write it to something like this:
Student.cs
public class Student
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<School> Schools { get; set; }
public Student()
{
Schools = new List<School>();
}
}
School.cs
public class School
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Student> Students { get; set; }
public School()
{
Students = new List<Student>();
}
}
StudentMap.cs
public class StudentMap : ClassMap<Student>
{
public Student()
{
Id(x => x.Id , "Student_Id");
Map(x => x.Name , "Name");
HasManyToMany(x => x.Schools).Table("LinkTable")
.ParentKeyColumn("Student_Id")
.ChildKeyColumn("School_Id");
}
}
SchoolMap.cs
public class SchoolMap: ClassMap<School>
{
public School()
{
Id(x => x.Id , "School_Id");
Map(x => x.Name , "Name");
HasManyToMany(x => x.Students).Table("LinkTable")
.ParentKeyColumn("School_Id")
.ChildKeyColumn("Student_Id");
}
}
If a student can only be associated with 0 or 1 schools, then you might consider dropping the LinkTable and the SchoolStudent class and just add School_Id to the Student table and a reference to School in the Student class.
Then your mappings are like:
public Student()
{
Id(x => x.Id);
Map(x => x.Name);
References(x => x.School);
}
public School()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Student).Inverse().Cascade.AllDeleteOrphan();
}

Fluent Nhibernate Many-to-Many mapping with extra column

I want to map sth like this using fluent Nhibernate but I am not sure how to map the inventory table
This is the tables I have :
Product (Id,Name, ...)
Warehouse(Id, Name, ...)
Inventory(Product_id, Warehouse_id, StockInHand)
and Mappings like below
Public ProductMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.StoresStockedIn)
.Cascade.All()
.Inverse()
.Table("Inventory");
}
public WarehouseMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasManyToMany(x => x.Products)
.Cascade.All()
.Table("Inventory");
}
The problem I face is that how can I map the StockInHand (how should the inventory model mapping?).
or are there other way to model this scenario ?
I have read some existing questions but not yet get clear understand what to do.
Thanks
Your relationship is not a many-to-many as far as NHibernate is concerned. A true many-to-many has no additional columns, such as StockInHand in your example.
You have to map this as two one-to-many relationships, and map Inventory as an entity.
Something like (i've skipped the other properties):
public class Product
{
public List<Inventory> Inventory { get; set; }
}
public class Warehouse
{
public List<Inventory> Inventory { get; set; }
}
public class Inventory
{
public Product Product { get; set; }
public Warehouse Warehouse { get; set; }
public bool StockInHand { get; set; }
}
public ProductMap() {
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Inventory)
.Cascade.All()
.Inverse()
.Table("Inventory");
}
public WarehouseMap()
{
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.Inventory)
.Cascade.All()
.Inverse()
.Table("Inventory");
}
public InventoryMap()
{
CompositeId()
.KeyReference(x => x.Product, "Product_id")
.KeyReference(x => x.Warehouse, "Warehouse_id")
Map(x => x.StockInHand);
}