Mapping Tables with shared foreign key in one to one relationship? - fluent-nhibernate

What is best way to map following classes?
I have classes where communication is "base" class as it contains shared data for either option. There can be only communication to ComSms or to ComEmail. The problem is i am unsure how to proceed with the mapping.
I would like if at all possible use one repository for accessing the Objects.
Class Set Up
public interface ICommunication
{
}
public Communication: ICommunication{
//PK and FK on this item
public virtual int CommunicationId{get;set;}
public virtual string Name {get;set;}
public virtual string Surname {get;set;}
public virtual DateTime Date{get;set;}
//I am expecting to switch on type between ComSms and ComEmail
public virtual Type {get;set;}
}
public ComSms : Communication{
public virtual string Number {get;set;}
public virtual string Text {get;set;}
}
public ComEmail : Communication{
public virtual string Subject{get;set;}
public virtual string Body {get;set;}
public virtual string Address {get;set;}
}
Database
Imagined usage
ICommunication smsToSave = new ComSms()
smsToSave.Name = "UserName";
smsToSave.Surname ="UserSurname";
smsToSave.Date = DateTime.Now;
smsToSave.Type = 1;
smsToSave.Number ="123456789";
smsToSave.Text = "Hello boys";
CommunicationRepository.Save(smsToSave)

I don't have time to write out any mappings but what you need is a discriminator. This would allow you to say have a CommunicationType foreign key in your table that could link to either the Sms or Email table. The nice thing about discriminators is that NHibernate takes care of everything for you.
And yes, seeing as your aggregate root is Communication then you could use one repository for accessing either of your communication types.

ok
i have resolved it by separated repositories that handles ever part of it instead
i could not bind it correctly, so chosen to go around the problem.
if you find any way of doing this please let me know

Related

Should I have both text and value in my model for a property that is selected from dropdownlist

In ASP.NET MVC application I have a model named CarSearchCriteria:
public class CarSearchCriteria{
public int CarMake {get;set;} // This is selected from a dropdownlist
public int YearOfFirstReg {get;set;}
public string ModelVariant {get;set}
}
I have two views - one for editing and the other one for viewing. In the editing view for the CarMake property I can do the following. I know I could have used DropDownListFor but didn't want to mess with SelectList for the time being:
<select name="CarMake">
<option value="1">BMW</option>
<option value="2">Mercedes</option>
<option value="3">Toyota</option>
</select>
So the model binding mechanism will easily bind the selected value to the appropriate model property. But what about the reading mode. I can't show 1s or 2s. I need to show BMW, Mercedes and so on. My question is what is the preferred way, do I have to have a property name that holds the actual textual information, something like CarMakeText?
You could have both the identifier (which you currently have) as well as the Make object itself. The latter would never need to be accessed when building the model, but can be accessed when reading the model. A lazy-loaded read-only property often works well for that. Something like this:
public int CarMakeID { get; set; }
public Make CarMake
{
get
{
if (CarMakeID == default(int))
return null;
// fetch the Make from data and return it
}
}
Naturally, this depends a lot on what a Make actually is and where you get it. If there's just some in-memory list somewhere then that should work fine. If fetching an instance of a Make is a little more of an operation (say, fetching from a database) then maybe some in-object caching would be in order in case you need to access it more than once:
public int CarMakeID { get; set; }
private Make _carMake;
public Make CarMake
{
get
{
if (CarMakeID == default(int))
return null;
if (_carMake == null)
// fetch the Make from data and save it to _carMake
return _carMake;
}
}
David's solution is just fine but for some reason I find my own solution to better fit my needs and besides that I find it more elegant. So basically what I do is I create a class that holds the textual descriptions of all the properties that keep just ID. For example, I have the following model:
public class EmployeeModel{
public int EmployeeID {get;set;}
public string FullName {get;set}
*public int DepartmentID {get;set}
*public int SpecialityID {get;set;}
public int Age {get;set;}
}
The properties marked with asterisk are the properties that keep ids of possible many predefined options and when showing we're supposed to show the actual descriptions, not the number representations. So for this purpose, we create a separate class:
public class EmployeeTextValues{
public string DepartmentName {get;set;}
public string SpecialityName {get;set;}
}
And then I just add this class as a property to my model:
public EmployeeTextValues TextValues {get;set;}
After that, it's quite easy to access it from anywhere, including Razor.
P.S. I'm sure that a lot of people will tend to do the following before initializing this property:
Employee emp=new Employee;
emp.Age=25;
emp.TextValues.DepartmentName="Engineering";// Don't do this
If you try to access or set Textvalues.Someproperty you'll get Object reference not set to an instance of an object. So do not forget to set TextValues first to some initialized object. Just a kind reminder, that's all.

remove from collection without load all collection data. confused which collection mapping to use

I have a many-to-many relationship between Assignment and User
When trying to delete an user from an assignment, I see all users are loaded in the collection.
How to I avoid that?
public class User
{
public virtual int Id { get; private set; }
public virtual IList<Assignment> Assignments { get; set; }
}
public class Assignment
{
public virtual int Id { get; private set; }
public virtual ICollection<User> Users { get; set; }
}
Mappings:
HasManyToMany(user => user.Assignments).Table("UserToAssignment").ParentKeyColumn("UserId").ChildKeyColumn("AssignmentId").Inverse().ExtraLazyLoad();
HasManyToMany(productAssignment => productAssignment.Users).AsSet().Table("UserToAssignment").ParentKeyColumn("AssignmentId").ChildKeyColumn("UserId").LazyLoad();
Calling code:
assignment.Users.Remove(user)
Initially I used Bag instead of Set for Assignment mapping, but when updating it, it was deleting and then reinserting alot of rows in the AssignmentsToUsers table. So I changed to using Set.
But now I see a problem with using Set: it brings all data in memory.
What is the recommended way of doing this?
You can't avoid this and I would ignore it if performance is acceptable. If performance is a problem, there are three ways I can think of to tackle it:
If the other side of the collection (User.Assignments) is lighter weight then remove the assignment from the user instead.
Model the many-to-many table and delete the object directly. You would have to be certain that the Users collection is not going to be loaded prior to this because the in-memory representation will still contain the deleted record.
Direct delete using SQL -- this has the same caveat as #2.
You should use extra lazy mode also for Assignment.Users.

How can ServiceStack.OrmLite ignore a property by attribute

public class User
{
public long Id {get;set;}
[References(typeof(City))]
public long CityId {get;set;}
[????]
public City {get;set;}
}
I'm trying to use ServiceStack.OrmLite. I'm using both ReferenceKey(CityId) and Reference (City). ReferenceKey is for Db creation, Reference is for using object in my code.
IgnoreAttribute .. Tested, it works.
Try the [IgnoreDataMember] attribute.
This attribute will tell the ServiceStack libraries to ignore this property.

Invalid index n for this SqlParameterCollection with Count=m

I'm getting this nasty error in Castle Active Record (wrapped around NHibernate) when I try to save a class:
Invalid index n for this SqlParameterCollection with Count=m
I know that this error is caused by a property being mapped multiple times in a class however I'm not sure how to get around it. I have two child classes that both map back to the class in question using the same column (IpAddressNumber). Also IpAddressNumber is the primary key of the class, which results in NHibernate trying to map the IpAddressNumber property three times (just a guess.)
Here is the class:
[ActiveRecord(Lazy=true)]
public class DeviceConfiguration : UsersDatabase<DeviceConfiguration>
{
[PrimaryKey]
public virtual long IPAddressNumber { get; set; }
[BelongsTo("IPAddressNumber", Lazy = FetchWhen.OnInvoke)]
public virtual Vehicle Vehicle { get; set; }
[BelongsTo("IPAddressNumber", Lazy = FetchWhen.OnInvoke)]
public virtual JBusConfiguration JBusConfiguration { get; set; }
}
Any help would be greatly appreciated...
I ended up having to just remove the second association altogether to get around this issue. Not a great solution but the only one I could find.

Question about Repositories and their Save methods for domain objects

I have a somewhat ridiculous question regarding DDD, Repository Patterns and ORM. In this example, I have 3 classes: Address, Company and Person. A Person is a member of a Company and has an Address. A Company also has an Address.
These classes reflect a database model. I removed any dependencies of my Models, so they are not tied to a particular ORM library such as NHibernate or LinqToSql. These dependencies are dealt with inside the Repositories.
Inside one of Repositories there is a SavePerson(Person person) method which inserts/updates a Person depending on whether it already exists in the database.
Since a Person object has a Company, I currently save/update the values of the Company property too when making that SavePerson call. I insert / update all of the Company's data - Name and Address - during this procedure.
However, I really have a hard time thinking of a case where a Company's data can change while dealing with a Person - I only want to be able to assign a Company to a Person, or to move a Person to another Company. I don't think I ever want to create a new Company alongside a new Person. So the SaveCompany calls introduce unnecessary database calls. When saving a Person I should just be able to update the CompanyId column.
But since the Person class has a Company property, I'm somewhat inclined to update / insert it with it. From a strict/pure point of view, the SavePerson method should save the entire Person.
What would the preferred way be? Just inserting/updating the CompanyId of the Company property when saving a Person or saving all of its data? Or would you create two distinct methods for both scenarios (What would you name them?)
Also, another question, I currently have distinct methods for saving a Person, an Address and a Company, so when I save a Company, I also call SaveAddress. Let's assume I use LinqToSql - this means that I don't insert/update the Company and the Address in the same Linq query. I guess there are 2 Select Calls (checking whether a company exists, checking whether an address exists). And then two Insert/Update calls for both. Even more if more compound model classes are introduced. Is there a way for LinqToSql to optimize these calls?
public class Address
{
public int AddressId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Company Company { get; set; }
public Address Address { get; set; }
}
Edit
Also see this follow up question. How are Value Objects stored in a Database?
I myself have used the IRepository approach lately that Keith suggests. But, you should not be focusing on that pattern here. Instead, there are a few more pieces in the DDD playbook that can be applied here.
Use Value Objects for your Addresses
First, there is the concept of Value Objects (VO) you can apply here. In you case, it would be the Address. The difference between a Value Object and an Entity Object is that Entities have an identity; VOs do not. The VO's identity really is the sum of it's properties, not a unique identity. In the book Domain-Drive Design Quickly (it's also a free PDF download), he explains this very well by stating that an address is really just a point on Earth and does not need a separate SocialSecurity-like identity like a person. That point on Earth is the combination of the street, number, city, zip, and country. It can have latitude and longitude values, but still those are even VOs by definition because it's a combination of two points.
Use Services for combining your entities into a single entity to act upon.
Also, do not forget about the Services concept in the DDD playbook. In your example, that service would be:
public class PersonCompanyService
{
void SavePersonCompany(IPersonCompany personCompany)
{
personRepository.SavePerson();
// do some work for a new company, etc.
companyRepository.SaveCompany();
}
}
There is a need for a service when you have two entities that need both need a similar action to coordinate a combination of other actions. In your case, saving a Person() and creating a blank Company() at the same time.
ORMs usualyl require an identity, period.
Now, how would you go about saving the Address VO in the database? You would use an IAddressRepository obviously. But since most ORMs (i.e. LingToSql) require all objects have an Identity, here's the trick: Mark the identity as internal in your model, so it is not exposed outside of your Model layer. This is Steven Sanderson's own advice.
public class Address
{
// make your identity internal
[Column(IsPrimaryKey = true
, IsDbGenerated = true
, AutoSync = AutoSync.OnInsert)]
internal int AddressID { get; set; }
// everything else public
[Column]
public string StreetNumber { get; set; }
[Column]
public string Street { get; set; }
[Column]
public string City { get; set; }
...
}
From my recent experience of using the repository pattern I think you would benefit from using a generic repository, the now common IRepository of T. That way you wouldn't have to add repository methods like SavePerson(Person person). Instead you would have something like:
IRepository<Person> personRepository = new Repository<Person>();
Person realPerson = new Person();
personRepository.SaveOrUpdate(realPerson);
This method also lends itself well to Test Driven Development and Mocking.
I feel the questions about behavior in your description would be concerns for the Domain, maybe you should have an AddCompany method in your Person class and change the Company property to
public Company Company { get; private set; }
My point is; model the domain without worrying about the how data will be persisted to the database. This is a concern for the service that will be using your domain model.
Back to the Repository, have a look at this post for good explanation of IRepository over LinqToSql. Mike's blog has many other posts on Repositories. When you do come to choose an ORM I can recommend HHibernate over LinqToSql, the latter is now defunct and NHibernate has a great support community.