Illegal access to loading collection in Fluent and Nhibernate - fluent-nhibernate

I'm not able to understand why the problem is occurring. Please let me know if there are any errors, I am very new to this topic.
public class Department
{
public virtual int Dept_id { get; set; }
public virtual String Dept_name { get; set; }
public virtual IList<Student> Students { get; set; }
//public virtual ICollection<Student> Students { get; set; }
public Department()
{
Students = new List<Student>();
}
}
public class Student
{
public Student()
{
}
//private int _Dept_id;
//public virtual Guid StudentId { get; set; }
public virtual Guid StudentId { get; set; }
/*public virtual int Dept_id
{
get { return this._Dept_id; }
set { this._Dept_id = value; }
}*/
public virtual int Dept_id { get; set; }
public virtual String Name { get; set; }
public virtual int Age { get; set; }
public virtual String Address { get; set; }
public virtual Department Department { get; set; }
}
public class DepartmentMap : ClassMap<Department>
{
public DepartmentMap()
{
Table("Department");
Id(x => x.Dept_id).Column("Dept_id");
Map(x => x.Dept_name).Column("Dept_name");
HasMany(x => x.Students).KeyColumn("Student_id").Inverse()
.Cascade.All();
}
}
public class StudentMap :ClassMap<Student>
{
public StudentMap()
{
Table("Student");
Id(x => x.StudentId).Column("Student_id").GeneratedBy.GuidComb();
Map(x => x.Name);
Map(x => x.Age);
Map(x => x.Address);
References(x => x.Department).Column("Dept_id")
.Not.Nullable().Not.LazyLoad();
}
}
Now when I am trying this code
[WebMethod(EnableSession = true)]
public List<Student> Students()
{
IList<Student> student = new List<Student>();
ISession session = NHibernateHelper.OpenSession();
student = session.Query<Student>().ToList();
return student.ToList();
}
it gives error in loading the students list inside the department as
illegal access to loading collection
What is lacking in this code and why this is happening?

sorry my bad !! there are cetain changes i made which made it working .. though not sure of apparent shortcomings of the mentioned idea below
changed student class as :
public class Student
{
public Student()
{
}
public virtual Guid StudentId { get; set; }
public virtual int Dept_id
{
get { return Department.Dept_id; }
set { this.Dept_id = Department.Dept_id; }
}
public virtual String Name { get; set; }
public virtual int Age { get; set; }
public virtual String Address { get; set; }
public virtual Department Department { get; set; }
}
and student mapping for the reference as
References(x => x.Department).Column("Dept_id").Cascade.All();
Note : there should be no single Dept Id mapping
and changed the DepartmentMap as :
public DepartmentMap()
{
Table("Department");
Id(x => x.Dept_id).Column("Dept_id");
Map(x => x.Dept_name).Column("Dept_name");
HasMany(x => x.Students).KeyColumn("Dept_id").AsBag();
}

Related

Fluent Nhibernate Composite Key mapping error

Composite Key mapping is not working in below scenario.
Database tables are as below.
Employee { Emp_ID, Name, Role_ID } (Role_ID is foreign key from Role table);
Leave { Leave_ID, Leave_Date, Leave_Comment};
Employee_Leave { Emp_ID, Leave_ID, Approval }; (EMP_ID and Leave_ID are composite key from Employee and Leave table respectively)
Entity classes are as below.
class Employee
{
public virtual string ID { get; set; }
public virtual string Name { get; set; }
public virtual Role EmpRole { get; set; }
}
public class Leave
{
virtual public Int16 LeaveID { get; set; }
virtual public String LeaveDate { get; set; }
virtual public String Comment { get; set; }
}
public class EmployeeLeaveApproval
{
public virtual string EMP_ID { get; set; }
public virtual int Leave_ID { get; set; }
public virtual string Approval { get; set; }
}
Mapping classes are as below.
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("Employee");
Id(x => x.ID, "ID");
Map(x => x.Name, "NAME");
References(x => x.EMPRole, "ROLE_ID").Not.LazyLoad();
}
}
public class LeaveMap : ClassMap<Leave>
{
public LeaveMap()
{
Table("Leave");
Id(x => x.LeaveID, "LEAVE_ID");
Map(x => x.LeaveDate, "LEAVE_DATE");
Map(x => x.Comment, "LEAVE_COMMENT");
}
}
Below class mapping is working fine.
public class EmployeeLeaveApprovalMap : ClassMap<EmployeeLeaveApproval>
{
public EmployeeLeaveApprovalMap()
{
Table("Employee_Leave");
Id(x => x.EMP_ID, "EMP_ID");
Map(x => x.Leave_ID, "LEAVE_ID");
Map(x => x.Approval, "Approval");
}
}
Below class mapping is not working.
public class EmployeeLeaveApprovalMap : ClassMap<EmployeeLeaveApproval>
{
public EmployeeLeaveApprovalMap()
{
Table("Employee_Leave");
CompositeId()
.KeyProperty(x => x.EMP_ID, "EMP_ID")
.KeyProperty(x => x.Leave_ID, "LEAVE_ID");
Map(x => x.Approval, "Approval");
}
}
Getting error "Database was not configured through Database method." while calling method BuildSessionFactory.
Many many thanks in advance for any help.
Found solution rather to say found the mistake i am doing.
Equal and GetHashCode methods are left being implemented in my code.
Below is the corrected entiity,
public class EmployeeLeaveApproval : Object
{
public virtual string EMP_ID { get; set; }
public virtual int Leave_ID { get; set; }
public virtual string Approval { get; set; }
public EmployeeLeaveApproval() {}
public override bool Equals(object obj)
{
if (obj == null)
return false;
EmployeeLeaveApproval EL = (EmployeeLeaveApproval)obj;
if (EL == null)
return false;
if (EMP_ID == EL.EMP_ID && Leave_ID == EL.Leave_ID)
return true;
return false;
}
public override int GetHashCode()
{
return (EMP_ID + "|" + Leave_ID).GetHashCode();
}
}
regards..Dharmendra

Fluent NHibernate - 1:1 Relationship with Nullable Field

Given the following model, I want to be able to enter a new WriteOffApprovalUser and have the Employee field be null. This is a 1:1 or null relationship.
public class WriteOffApprovalUser
{
public virtual string UserName { get; set; }
public virtual Employee Employee { get; set; }
}
public class Employee
{
public virtual string EmployeeID { get; set; }
public virtual string EmployeeStatusCode { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string JobTitle { get; set; }
public virtual string Division { get; set; }
public virtual string Department { get; set; }
public virtual string Location { get; set; }
public virtual string City { get; set; }
public virtual string DeskLocation { get; set; }
public virtual string MailID { get; set; }
public virtual string Phone { get; set; }
public virtual string PreferredName { get; set; }
public virtual string Fax { get; set; }
public virtual string SecCode { get; set; }
public virtual string SupervisorID { get; set; }
public virtual string UserId { get; set; }
}
Class Maps
public class WriteOffApprovalUserMap : ClassMap<WriteOffApprovalUser>
{
public WriteOffApprovalUserMap()
{
Table("WRITEOFF_APPROVAL_USER");
Id(x => x.UserName).Column("USER_NAME");
//Map(x => x.Employee).Nullable();
HasOne(x => x.Employee)
.Class<Employee>()
.Constrained()
.Cascade.SaveUpdate()
.PropertyRef("UserId");
}
}
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
Table("ADP_EMPLOYEE");
Id(x => x.EmployeeID).Column("EMPLID").GeneratedBy.Native("");
Map(x => x.FirstName).Column("FIRST_NAME");
Map(x => x.LastName).Column("LAST_NAME");
Map(x => x.PreferredName).Column("PREFERRED_NAME");
Map(x => x.UserId).Column("USER_ID");
}
}
Query/Save
using (var session = SessionProvider.GetSession())
{
using (var tx = session.BeginTransaction())
{
var user = new WriteOffApprovalUser() { UserName = "SAMSTR" };
session.Save(user);
tx.Commit();
}
}
This complains that Employee is null. How do I specify that Employee can be null?
Also, do all Id fields have to be integral? A lot of the keys on our tables are strings.
First off all if you put it as 1:1 it shouldn't be NULL because it's not correct design.
But here is an example of how to do so:
1) One way
HasOne(x => x.Employee)
.Class<Employee>().Nullable().NotFound.Ignore().PropertyRef("UserId");
2) Second way
References(x => x.Category).Column("UserId").Nullable().NotFound.Ignore();

Nhibernate Mapping relationships on multiple columns

I'm having problems mapping a relationaship between two entities when there are two columns involved in the mapping.
I'm modelling a state machine with two object types - State and Transition. Each process has its own state machine, so States and Transitions need to be identified by ProcessId. My entity classes are like this:
public class State
{
public virtual long Id { get; set; }
public virtual int ProcessId { get; set; }
public virtual int Ordinal { get; set; }
public virtual Process Process { get; set; }
public virtual ICollection<Transition> TransitionsIn { get; set; }
public virtual ICollection<Transition> TransitionsOut { get; set; }
}
public class Transition
{
public virtual long Id { get; set; }
public virtual long ProcessId { get; set; }
public virtual int FromStateNum { get; set; }
public virtual int ToStateNum { get; set; }
public virtual long StateActionId { get; set; }
public virtual Process Process { get; set; }
public virtual StateAction StateAction { get; set; }
public virtual State FromState { get; set; }
public virtual State ToState { get; set; }
}
I need the navigation properties (State.TransitionsIn, State.TransitionsOut, Transition.FromState, Transition.ToState) to be based on the ProcessId and the Ordinal number of the state. For example, Transition.FromState should navigate to the entity where t.ProcessId = s.ProcessId and t.FromStateNum = s.Ordinal.
I've tried the following mapping, but it complains that I'm using two columns to map to one (StateId).
public class StateMap : ClassMap<State>
{
public StateMap()
{
Id(x => x.Id);
HasMany(s => s.TransitionsIn)
.KeyColumns.Add("ProcessId", "ToStateNum")
.Inverse();
HasMany(s => s.TransitionsOut)
.KeyColumns.Add("ProcessId", "FromStateNum")
.Inverse();
}
}
public class TransitionMap : ClassMap<Transition>
{
public TransitionMap()
{
Id(x => x.Id);
References(t => t.FromState)
.Columns("ProcessId", "Ordinal");
References(t => t.ToState)
.Columns("ProcessId", "Ordinal");
}
}
How can I get this to work?
How about this mapping.. I have not tested it but just trying to give a direction.
public class StateMap : ClassMap<State>
{
public StateMap()
{
Id(x => x.Id);
HasMany(s => s.TransitionsIn)
.KeyColumn("ProcessId")
.KeyColumn("ToStateNum").PropertyRef("Ordinal")
.Inverse();
HasMany(s => s.TransitionsOut)
.KeyColumn("ProcessId")
.KeyColumn("FromStateNum").PropertyRef("Ordinal")
.Inverse();
}
}
public class TransitionMap : ClassMap<Transition>
{
public TransitionMap()
{
Id(x => x.Id);
References(t => t.FromState)
.Columns("ProcessId", "FromStateNum");
References(t => t.ToState)
.Columns("ProcessId", "ToStateNum");
}
}

Fluent NHibernate Mapping Error

I am getting the following error using Fluent:
12:16:47,879 ERROR [ 7]
Configuration [(null)]- An association
from the table Address refers to an
unmapped class: System.Int32
NHibernate.MappingException: An
association from the table Address
refers to an unmapped class:
System.Int32
public class Address {
public Address() {
}
public virtual int AddressId {
get;
set;
}
public virtual string AddressLine1 {
get;
set;
}
public virtual string AddressLine2 {
get;
set;
}
public virtual string AddressLine3 {
get;
set;
}
public virtual string BuildingNumber {
get;
set;
}
public virtual string City {
get;
set;
}
public virtual string County {
get;
set;
}
public virtual System.DateTime MovedIn {
get;
set;
}
public virtual System.DateTime MovedOut {
get;
set;
}
public virtual int PersonId {
get;
set;
}
public virtual string PostCode {
get;
set;
}
}
public class AddressMap : ClassMap<Address> {
public AddressMap() {
Table("Address");
LazyLoad();
Id(x => x.AddressId).GeneratedBy.HiLo("1000");
Map(x => x.AddressLine1).Length(100).Not.Nullable();
Map(x => x.AddressLine2).Length(100).Not.Nullable();
Map(x => x.AddressLine3).Length(100).Not.Nullable();
Map(x => x.BuildingNumber).Length(250).Not.Nullable();
Map(x => x.City).Length(250).Not.Nullable();
Map(x => x.County).Length(250).Not.Nullable();
Map(x => x.MovedIn).Not.Nullable();
Map(x => x.MovedOut).Not.Nullable();
References(x => x.PersonId).Column("PersonId").Not.Nullable();
Map(x => x.PostCode).Length(15).Not.Nullable();
}
}
[TestFixture]
public class TestBase
{
protected SessionSource SessionSource { get; set; }
protected ISession Session { get; private set; }
[SetUp]
public void SetupContext()
{
var cfg = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(
"Data Source=localhost;Initial Catalog=ted;User ID=sa;Password=xxxx;"));
SessionSource = new SessionSource(cfg.BuildConfiguration()//**Error Here**
.Properties, new TestModel());
Session = SessionSource.CreateSession();
SessionSource.BuildSchema(Session);
}
[TearDown]
public void TearDownContext()
{
Session.Close();
Session.Dispose();
}
}
I get an error on my initial configuration, I have been over it a few times and I am really unsure what exactly I am doing wrong? Can anyone see anything Obvious? I can confirm there is only 2 int's in the database for this table. AddressId - Non identity PK and PersonId non identity FK
You should have a Person property of type Person, not an id.
Suggested read: https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started

How am I supposed to query for a persisted object's property's subproperty in nhibernate?

I'm feeling dumb.
public class Uber
{
public Foo Foo { get; set; }
public Bar Bar { get; set; }
}
public class Foo
{
public string Name { get; set; }
}
...
var ubercharged = session.CreateCriteria(typeof(Uber))
.Add(Expression.Eq("Foo.Name", "somename"))
.UniqueResult<Uber>();
return ubercharged;
This throws a "could not resolve property" error.
What am I doing wrong? I want to query for an Uber object that has a property Foo which has a Name of "somename".
updated with real life example, repository call, using fluent nhibernate:
public UserPersonalization GetUserPersonalization(string username)
{
ISession session = _sessionSource.GetSession();
var personuser = session.CreateCriteria(typeof(UserPersonalization))
.Add(Expression.Eq("User.Username", username))
.UniqueResult<UserPersonalization>();
return personuser;
}
The classes/mappings:
public class User
{
public virtual Guid UserId { get; set; }
public virtual string Username { get; set; }
public virtual string Email { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string PasswordSalt { get; set; }
public virtual bool IsLockedOut { get; set; }
public virtual bool IsApproved { get; set; }
}
public class Person
{
public virtual int PersonId { get; set; }
public virtual string Name { get; set; }
public virtual Company Company { get; set; }
}
public class UserPersonalization
{
public virtual int UserPersonalizationId { get; set; }
public virtual Person Person { get; set; }
public virtual User User { get; set; }
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Id(x => x.UserId).GeneratedBy.Guid().ColumnName("UserId");
Map(x => x.Username);
Map(x => x.PasswordHash);
Map(x => x.PasswordSalt);
Map(x => x.Email);
Map(x => x.IsApproved);
Map(x => x.IsLockedOut);
}
}
public class UserPersonalizationMap : ClassMap<UserPersonalization>
{
public UserPersonalizationMap()
{
WithTable("UserPersonalization");
Id(x => x.UserPersonalizationId).ColumnName("UserPersonalizationId");
References(x => x.Person).ColumnName("PersonId");
References(x => x.User).ColumnName("UserId");
}
}
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.PersonId).ColumnName("PersonId");
Map(x => x.Name);
References(x => x.Company).ColumnName("CompanyId");
}
}
Try this:
var ubercharged = session.CreateCriteria(typeof(Uber))
.CreateCriteria("Foo")
.Add(Restrictions.Eq("Name", "somename"))
.UniqueResult<Uber>();
Can you sort using "ubercharged.AddOrder(Order.asc("Foo.Name")) syntax? This syntax should work in NHib 2.01. If not, your maps are not working correctly.
Stuart's answer should work fine for you though.