Self referencing a table - nhibernate

so I'm new to NHibernate and have a problem. Perhaps somebody can help me here.
Given a User-class with many, many properties:
public class User
{
public virtual Int64 Id { get; private set; }
public virtual string Firstname { get; set; }
public virtual string Lastname { get; set; }
public virtual string Username { get; set; }
public virtual string Email { get; set; }
...
public virtual string Comment { get; set; }
public virtual UserInfo LastModifiedBy { get; set; }
}
Here some DDL for the table:
CREATE TABLE USERS
(
"ID" BIGINT NOT NULL ,
"FIRSTNAME" VARCHAR(50) NOT NULL ,
"LASTNAME" VARCHAR(50) NOT NULL ,
"USERNAME" VARCHAR(128) NOT NULL ,
"EMAIL" VARCHAR(128) NOT NULL ,
...
"LASTMODIFIEDBY" BIGINT NOT NULL ,
) IN "USERSPACE1" ;
Database-table-field 'LASTMODIFIEDBY' holds for auditing purposes the Id from the User who is acting in case of inserts or updates. This would normally be an admin.
Because the UI shall display not this Int64 but admins name (pattern like 'Lastname, Firstname') I need to retrieve these values by self referencing table USERS to itself. Next is, that a whole object of type User would be overkill by the amount of unwanted fields. So there is a class UserInfo with much smaller footprint.
public class UserInfo
{
public Int64 Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string FullnameReverse
{
get { return string.Format("{0}, {1}", Lastname ?? string.Empty, Firstname ?? string.Empty); }
}
}
So here starts the problem. Actually I have no clue how to accomplish this task. Im not sure if I also must provide a mapping for class UserInfo and not only for class User. I'd like to integrate class UserInfo as Composite-element within the mapping for User-class. But I dont no how to define the mapping between USERS.ID and USERS.LASTMODIFIEDBY table-fields.
Hopefully I decribes my problem clear enough to get some hints. Thanks alot!

This looks like a bad case or premature optimization.
Are you really having any performance issues if you define LastModifiedBy as User and use <many-to-one> to map it?
That should be your starting point.

Related

Identity Column Inserting Null With MVC Code First

I am using MVC to generate my database. I have the following code structure in my UserProfile class:
[KeyAttribute()]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
This generates the database fine, but when I try to insert a record it says UserId cannot be null. I cannot figure out why it isn't auto generating an Id integer.
This was because I had some issues updating the database. Needed to manually drop this table and re-create it. Is working fine now.

ASP MVC 4 Mapping one to one relationship code first

I am new to ASP MVC and am working on a project with complex related data model. so while working on the relationships i looked online and got the following example on the Blog of asps.net :
namespace CodeFirst.Associations.OneToOneFK
{
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int BillingAddressId { get; set; }
public int DeliveryAddressId { get; set; }
public Address BillingAddress { get; set; }
public Address DeliveryAddress { get; set; }
}
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
}
So my doubt is do we really need both the int BillingAddressID as well as Address BillingAddress?
Also, how do we associate an address to a user if we don't use AddressID.
Thanks for the help. :)
int BillingAddressID is called a foreign key property.
BillingAddress is called a navigation property (in this case a reference navigation property).
Foreign key properties aren't required to define a relationship, but they do simplify certain coding patterns. The general recommendation is to use both navigation properties and foreign key properties.
See here for more information about why FK associations were introduced.

MVC4 how to load related data without Navigation Properties

I an fairly new to MVC, and have created an MVC4 application using EF-database-first. The database does not contain foreign key definitions and I can't add them (I don't own the database). Here are two example classes from the database:
public partial class Allocation
{
public int AllocID { get; set; }
public int DeptID { get; set; }
public decimal AllocationPercent { get; set; }
}
public partial class Department
{
public int DeptID { get; set; }
public string DeptName { get; set; }
public string Account { get; set; }
}
The default Allocation Index page shows the department ID. I want to show the department name instead. How can I do this without navigation properties?
I tried
public class AllocationController : Controller
{
private Entities db = new Entities();
//
// GET: /Allocation/
public ActionResult Index()
{
return View(db.Allocation.Include(d => d.DeptID).ToList());
}
...
but this gives an error ("A specified Include path is not valid. The EntityType 'TESTModel.Allocation' does not declare a navigation property with the name 'DeptID'.")...
I'm not sure how to code eager-loading or explicit-loading without navigation properties either, which prompted this question. Efficiency-wise, I don't believe it matters which way I load the related information, so any help in any direction would be appreciated.
The database does not have to have definitions, as long as the fields are there and the entities have been placed in the database with referential integrity in mind. All you need to do is let entity framework know about the relationship. This is done with the virtual keyword to create "Navigational Properties".
public partial class Allocation
{
public int AllocID { get; set; }
public int DeptID { get; set; }
public decimal AllocationPercent { get; set; }
public virtual Department Department { get; set; } /* this is your nav property */
}
public partial class Department
{
public int DeptID { get; set; }
public string DeptName { get; set; }
public string Account { get; set; }
}
Now you can do:
db.Allocation.Include(a => a.Department).ToList()
There may be an error which requires you to use a foreign key definition (although I do not think so). If this is the case, you will need to decorate your navigation property like this
[ForeignKey("DeptID")]
public virtual Department Department { get; set; }
You may also try it this way:
public int AllocID { get; set; }
[ForeignKey("Department")]
public int DeptID { get; set; }
public decimal AllocationPercent { get; set; }
public virtual Department Department { get; set; }
With navigation properties, Travis J's answer is what you need.
If you don't want to use navigation properties, assuming your DB context has a set called Departments, you could do smth like this:
var deptId = db.Allocation.DeptID;
var departments = db.Departments.Where(p => p.DeptID == deptId);
return View(departments.ToList());

Entity Framework and using Fluent API for mapping two entities to another one

Scenario seems to be trivial and I'm really confused on what I'm doing wrong.
So, I have a Client class
public class Client
{
[Key]
public int ClientID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Account Account { get; set; }
}
Employee class
public class Employee
{
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Account Account { get; set; }
}
and an Account class
public class Account
{
[Key]
public int AccountID { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public virtual Employee Employee { get; set; }
public virtual Client Client { get; set; }
}
Both Client and Employee may have an Account or not ( online access is optional ). As database is not compatible with EF namingconvention I have to come up with Fluent API explicit mappings.
Both Client and Employee tables have "AccountID" column that I'm trying to use to build a relation.
modelBuilder.Entity<Client>()
.HasOptional(e => e.Account)
.WithRequired(a => a.Client)
.Map(m => m.MapKey("AccountID"));
modelBuilder.Entity<Employee>()
.HasOptional(e => e.Account)
.WithRequired(a => a.Employee)
.Map(m => m.MapKey("AccountID"));
but I get
Schema specified is not valid. Errors:
(15,6) : error 0019: Each property name in a type must be unique. Property name 'AccountID' was already defined.
(16,6) : error 0019: Each property name in a type must be unique. Property name 'AccountID' was already defined.
so, is there a way to fix this other than modification of the table/entity structure?
Turns out you don't need Fluent API in this case, what you need is to DataAnnotate your properties in Entities with InverseProperty attribute
[InverseProperty("AccountID")]
There is a great answer by Ladislav Mrnka in Entity Framework 4.1 InverseProperty Attribute question
However if anyone knows how to do that correctly with Fluent answers are highly appreciated

NHibernate - QBE

I have a problem using QBE with NHibernate. I have a one-to-one relationship between a Person class and an Employee.
public class Person
{
public virtual Employee Employee { get; set; }
public virtual int Age { get; set; }
public virtual string Forename { get; set; }
public virtual string Surname { get; set; }
public virtual int PersonID { get; set; }
}
public class Employee
{
public virtual int PersonID { get; set; }
public virtual string PayRollNo { get; set; }
public virtual int Holidays { get; set; }
public virtual Person Person { get; set; }
}
As an example, I want to get all Employees where Employee.Forename="John" and Employee.Person.PayRollNo = "231A". I was wondering if I could use Query By Example to do this?
I have not been able to find a definitive "no" but I haven't been able to get this work. I've found that QBE is promising but unfortunately not very useful due to the following limitations:
Cannot query related objects.
Requires public parameterless constructor.
Initialized properties are included in query unless specifically excluded using ExcludeProeprty. For example, bool properties are restricted to false in the where clause, DateTime as DateTime.MinValue. This makes the query very brittle because class modifications may have bad side effects.