Domain Design and NHibernate - nhibernate

Given the database design below how would you model it? Address Type is Bussiness/Home etc and the PersonId is on Address table is because there are many addresses for one Person.
I would most do something like:
public class Person
{
public virtual int PersonId { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName{ get; set; }
public virtual DateTime DOB{ get; set; }
public virtual IList<Address> Addresses { get; set; }
}
public class Address
{
public virtual int AddressId{ get; set; }
public virtual Person Resident{ get; set; }
public virtual AddressType Location{ get; set; }
public virtual string PostalCode{ get; set; }
public virtual string FullAddress{ get; set; }
}
public class AddressType
{
public virtual int AddressTypeId{ get; set; }
public virtual string Description{ get; set; }
public virtual IList<Address> Addresses { get; set;}
}
however I have no idea if this is appropriate.
I have always done my models with objects and have never left int's in place. NHibernate Mapping will easily replace these with the objects and then lazy/eager load them, so I just figure this is the best option. Opinions?

The domain looks clean.
The only think I'd think twice about is the renaming of some property/column names, which can lead to confusion.

I would model it like it is in reality, Person has several addresses and each can be of a different type, leaving out all the database id fields. That will make your NHibernate Configurations and queries a little bit harder to create, but your domain model will be much easier to work with.

I suggest convert relations Address-Person and Address-AddressType to on way relations. It not very usable if each Address now its Person (resident) and each AddressType now its Address (addresses). By doing this your will be very simpler.
Additionally it seems meaningless to have a unique person for each address. Imagine you are saving some persons in your model that they are just one family that all together live in an one home. Consequently all of them have same address.

I would change the Address and AddressType many to one relationship. It is actually one-to-one and in which case, AddressType would go in the Address table as a field. That is the best form IMHO.

Related

How to create mapping relationship using Fluent NHibernate

How can I map one-to-many relationship with
User to Address,
Customer to Address,
Agency to Address and
store in a single Address Table using Fluent NHibernate
public class User
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Address> Address { get; set; }
}
public class Customer
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Address> Address { get; set; }
}
public class Agency
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Address> Address { get; set; }
}
public class Address
{
public virtual int Id { get; set; }
public virtual string Address1 { get; set; }
public virtual string Address2 { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
}
I think you'll need to store your relations independently to connect addresses and users/customers/agencies if you want to be able to use the same address for all types. This involves introducing a new table that only stores ID pairs, and making that the storage location for your relationship.
You can map collections as many-to-many and use the table method to name your link table. Your mapping would look something like:
public UserMap : ClassMap<User> {
Id (u => u.Id);
Map (u => u.Name);
HasManyToMany (u => u.Addresses).Table ("UsersXAddresses");
}
You'll need a similar link table for customers and agencies.
In the constructor for your mapping class, map the link using the HasMany method. HasMany will create a one-to-many relationship. HasManyToMany will create a many-to-many relationship.
For example: HasMany(x => x.Address).LazyLoad();
This will create a one-to-many relationship between the User class and the Address class.
For the many-to-many, you will also need to specify the table name and if you so desire, the left and right side table mappings.
For example: HasManyToMany(x => x.Address).Table("AddressToUser").ParentKeyColumn("AddressId").ChildKeyColumn("UserId").LazyLoad();
If you decide that you want to set up a distinction between a UserAddress and an AgencyAddress (where these are sub-classes of Address) - you can use the DiscriminateSubClassesOnColumn method in the AddressMap class so the FNH knows to create an extra column in order to determine which type of object to create.
For example: DiscriminateSubClassesOnColumn("Type").AlwaysSelectWithValue();
You should be able to use FNH Automapping to map these classes "as is".
It will handle all the relationships in your object model.
I believe it will put all the addresses in a single Address table as you desire, but can't say for sure.

How to use components in fluent nhibernate

I'm working on a legacy MySql database and have the following entities:
public class Company
{
public int Id { get; set;}
public string Address { get; set; }
public string City { get; set; }
}
public class CompanyDepartment
{
public int Id { get; set;}
public string Address { get; set; }
public string City { get; set; }
}
The idea is that a company only use the department class if it has more than one department.
Right now I'm trying to make a company/department search, this means I need a list of all departments and therefore I need to "create" departments of all the companies that only has one department, and therefore don't have a entry in CompaynyDepartment.
To do this I was thinking of use components in fluent NHibernate, but I'm not sure I can join the real departments with the fake ones?
Is there a better approach to this problem? It's not an option to change the database structure.
I ended up changing the database structure

FluentNHibernate mapping syntax help needed

I'm having some trouble figuring out the appropriate FluentNHibernate mapping syntax for the following data model and domain objects. Here's the data model I'm working against:
And I'm trying to map the following domain objects to that model:
namespace FluentNHibernateSandbox.Entities
{
public abstract class EntityBase
{
public virtual long Id { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Attribute : EntityBase
{
public virtual string Name { get; set; }
public virtual string Label { get; set; }
public virtual string Description { get; set; }
public virtual int SortOrder { get; set; }
public virtual Group Group { get; set; }
public virtual Editor Editor { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Group : EntityBase
{
public virtual string Name { get; set; }
public virtual string Label { get; set; }
public virtual string Description { get; set; }
public virtual int SortOrder { get; set; }
public virtual IList<Attribute> Attributes { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Editor : EntityBase
{
public virtual string ViewName { get; set; }
public virtual string WorkerClassName { get; set; }
}
}
In general, what I ultimately want doesn't seem like it should be all that hard to do, but I after having tried just about every combination of mappings I can think of, I still can't seem to get it right. I just need my Attribute to have a reference to the Group that it belongs to and a reference to the Editor assigned to it, and each Group should have a collection of the Attributes that are part of it. The couple of many-to-many join tables are what seem to be giving me fits. Particularly the APPLICATION_ATTRIBUTE table. Ultimately I only want the Attributes that my application is concerned with, in this case, those with an APPLICATION_ID of 4.
Any help would be greatly appreciated. Thanks.
Really kinda surprised nobody responded to this at all, but anyway. The answer/solution for this mapping situation that we came up with, which I was trying to avoid to start with, but turned out to really be the best way to go, was to create some custom views in the database that joined together all of the application-specific data I needed, and then just mapped my application's domain objects to those views. This worked at least partially because the information I needed from these tables is going to be read-only for this application, but even if I needed to write to the tables, I'm pretty sure (though haven't verified as I didn't really have need in this case) that I could have setup my views to be writeable and that would've worked too.
Hat tip to #robconery.

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.

Fluent NHibernate Automap Joined Sub-Class Setting the Key

When automapping a joined subclass in fluent nhibernate, I can't figure out how to give the joined subclass a primary key.
public class Address:Entity {
public virtual string Address1 { get; set; }
public virtual string Address2 { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string Zip { get; set; }
public virtual string Phone { get; set; }
public virtual string Fax { get; set; }
public virtual IList<Location> Locations { get; set; }
}
public class Location:Address {
public virtual Address BillingAddress { get; set; }
public virtual string OfficeHours { get; set; }
public virtual string PatientAgeRestrictions { get; set; }
public virtual bool WheelchairAccess { get; set; }
public virtual string ContactPerson { get; set; }
public virtual string ContactEmail { get; set; }
public virtual string ContactPhone { get; set; }
public virtual string ContactFax { get; set; }
public virtual string TaxId { get; set; }
}
I want Location to have it's own id "location_ id" with it's own sequence. Then I want that mapped to address through an address_id column.
Right now it's generating the location with "addressid" as the primary key, which isn't what I want. How do I change this with the automapping?
I'm not sure you have a joined-subclass relationship. That is, by definition a joined subclass has the same ID as its parent class. For example, you might have a Person entity stored in your database for generic "people" information like name/age/etc and then an Employee subclass entity which is stored in a different table and holds data like position, salary, and dates of employment. So an Employee is a subtype of Person and to get the full "Employee-Person" object, you must join the two tables on their primary keys (e.g. SELECT * FROM Employee INNER JOIN Person ON Employee.Employee_id = Person.Person_id).
Are you sure about your relational model here? Is Location truly a subtype of Address? Inferring a bit from your property names, it seems to me that this is not what you intend. It seems like you probably have a many-to-many between an Address and an Organization (that is, there may be many "organizations" at the same address and an "organization" may have many addresses), with a "contact person" for the organization at a specific address. In which case you should map "organization", "contact", and another entity that defines the relationship between Address and "organization".