One controller/view for entities with same properties? (DRY code) - asp.net-mvc-4

We have quite a few lookup entities that all have the same structure - just ID and Name. For example, Gender, Ethnicity are just dropdown lists on a Patient view. Each lookup entity has views for viewing/adding/editing the values. Each entity has its own controller with nearly identical actions - Index (view list), Create, and Edit. The only thing different is the type.
Is there a way to create one controller and one set of views to manage all of these lookup entities using generics, a base entity, some other technique or a combination of these?

One simple thing you can do is create an Interface for ID and Name. Then inherit it in the models that you need to.
Example
public interface IEntity
{
int Id { get; set; }
string Name { get; set; }
}
Inherit this in your models
public class Gender : IEntity
{
}

Related

Data Annotation for a model consisting of multiple tables in database

I have a form displaying fields from 2 tables in database.
I want to validate this form using Data Annotation model validation technique in MVC4.
I am confused whether Data Annotation validation attributes should be applied to individual models(tables) or should I create separate model consisting of fields from both tables.
You should create a new model containing the information you want to display on your view. This specific model has a name: it's called view model. You should always pass view models to your views from the controller actions and your controller actions should always take view models as parameters. Then you could decorate the properties on this view model with validation attributes.
You can do both things. You can decorate your domain model classes and view models. Both things are correct. The thing is that for your view, it's better to use a view model instead of model classes. No need to expose the whole domain model in you view
Just add using System.ComponentModel.DataAnnotations;namespace and add the attributes you need on each property.
For example:
public class BankAccount
{
[Required]
public Person Person { get; set; }
[Required]
public AccountType AccountType { get; set; }
[Required, StringLength(256)]
public string BankName { get; set; }
}

How to prevent Nhibernate from fetching derived class?

I am using Nhibernate and I have a problem when fetching a base class with multiple derived classes (each class mapping a different table). When I watch the request, Nhibernate joins on every derived tables which has a huge an impact on the performances...
Here is a simplified vision of my classes :
public class Animal{
public virtual int ID { get; set;}
public virtual string Name { get; set;}
}
public class Dog : Animal{
//others properties
}
public class Cat: Animal{
//others properties
}
public class Person{
public virtual int ID { get; set;}
public virtual IEnumerable<Animal> Animals { get; set;}
}
A person has a list of Animals and I just want their names. The example is not perfect and more it's more complicated (a banking program) but it reflect well my problematic.
I KNOW it can be done differently etc, but it is a legacy so I don't have a choice...
Thanks in advance.
IMO NHibernate will only joind tables which contain projected columns. define a query but do not return Person but project into a dto/anonymous class the properties you need
After all, I created a class AnimalBase which is inherited by Dog, Cat and so forth and a class Animal without any child (both having the interface IAnimal).
As in 95% of my request, I only need Animal, I reference this class in my other objects like Person.
Not perfect but I did not find anything better...
Thanks Firo for your help.

Mapping to a different view based on child type

So i have a situation where i have common base type but i need to map to a different view based on the child type.
It looks like i can use a generic mapping class to handle the inheritance
http://geekswithblogs.net/nharrison/archive/2010/07/09/inheriting-a-class-map-in-fluent-nhibernate.aspx
But how can i conditionally map to a different view based on the child type? I see an EntityType property but it says its obsolete and will be made private in the next version.
As an example i have a base class of ContactInfo is standard between contact types but the values come from different places depending on the contact type, this I'll handle through the sql view.
using any mapping the referenced entity comes from a different table
class ContactInfo
{
public virtual long Id { get; set; }
public virtual ContactDetails Details { get; set; }
}
public ContactInfoMap
{
...
ReferencesAny(x => x.Details)
.EntityIdentifierColumn("details_id")
.EntityTypeColumn("contactType")
.IdentityType<long>()
.AddMetaValue<FooContactDetails>("1")
.AddMetaValue<BarContactDetails>("4");
}

Fluent NHibernate: How to create one-to-one bidirectional mapping?

I had a similar question to Fluent NHibernate: How to create one-to-many bidirectional mapping? but I was interested in the situation when I have a one-to-one mapping. For instance
Umbrealla
ID
Owner
UmbreallaOwner
ID
Umbrella
As we know each umbrella can only be owned by one person and nobody owns more than one umbrella. In a fluent map I would have something like
UmbrellaMap()
{
Id(x=>x.ID);
References<UmbrellaOwner>(x=>x.Owner);
}
UmbrellaOwnerMap()
{
Id(x=>x.ID);
References<Umbrella>(x=>x.Umbrella);
}
When creating the tables fluent will create a field in umbrella referncing the ID of umbrellaOwner and a field in umbrellaOwner referencing umbrella. Is there any way to change the mapping such that only one foreign key will be created but the Umbrella property and the Owner property will both exist? The examples I have seen involve setting the relations up in both directions so adding a new Umbrella looks like
AddUmbrealla(UmbrellaOwner owner)
{
var brolly = new Umbrella();
brolly.Owner = owner;
owner.Umbrella = brolly;
session.Save(owner); //assume cascade
}
which seems logical but a bit cumbersome.
Well, a reference is a reference; one object has a reference to the other. The reverse is not necessarily true.
In your case, you MIGHT get away with a HasOne relationship. However, HasOne is normally for denormalized data. Say you wanted more info about the owner, but you could not change Owner's schema because other code depended on it. You'd create an AdditionalOwnerInfo object, and create a table in the schema in which the OwnerID field of the table was a foreign key to Owner, and also the primary key of the table.
Ayende recommends a two-sided References() relationship in 99.9% of one-to-one cases, where the second object is conceptually separate from the first, but there is an implicit "I alone own exactly one thing" type of relationship. You can enforce the "one and one only" nature of the reference using a Unique().Not.Nullable() modifier set on the References mapping.
To streamline the referential setup, consider defining one object (UmbrellaOwner) as the "parent" and the other (Umbrella) as the "child", and in the parent's property setter, set the child's parent to the current reference:
public class Umbrella
{
public virtual string ID { get; set; }
public virtual Owner Owner { get; set; }
}
public class UmbrellaOwner
{
public virtual string ID { get; set; }
private Umbrella umbrella;
public virtual Umbrella Umbrella
{
get{
return umbrella;
}
set{
umbrella = value;
if(umbrella != null) umbrella.Owner = this;
}
}
}
Now, when you assign the child to the parent, the backreference is automagically set up:
var owner = new UmbrellaOwner{Umbrella = new Umbrella()};
Assert.AreEqual(owner, owner.Umbrella.Owner); //true;

Do I have to implement Add/Delete methods in my NHibernate entities?

This is a sample from the Fluent NHibernate website:
Compared to the Entitiy Framework I have ADD methods in my POCO in this code sample using NHibernate. With the EF I did context.Add or context.AddObject etc... the context had the methods to put one entity into the others entity collection!
Do I really have to implement Add/Delete/Update methods (I do not mean the real database CRUD operations!) in a NHibernate entity ?
public class Store
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public virtual IList<Employee> Staff { get; set; }
public Store()
{
Products = new List<Product>();
Staff = new List<Employee>();
}
public virtual void AddProduct(Product product)
{
product.StoresStockedIn.Add(this);
Products.Add(product);
}
public virtual void AddEmployee(Employee employee)
{
employee.Store = this;
Staff.Add(employee);
}
}
You don't have to do this for nhibernate, you have to do this for keep in-memory consistence and not repeat yourself.
Consistence in memory
If you have a two way relationship, lets say Order has Lines, and Line as a relationship to order. You don't want to have a reference from one side and not from the other.
If you just do:
order.Lines.Add(line);
You have made a reference from Order to Line, but Line.Order property remains null. So your in-memory instances are not consistent.
Don't Repeat Yourself
You can use the following code :
order.Lines.Add(line);
line.Order = order;
but you will be repeating yourself, so it is better to put this code in only one place, and the best place is as order.AddLine(..).
You don't have to. You could just call SomeStore.Products.Add(someProduct) directly from outside of your entity. But it's often good practice to make the collections 'read-only' from a public perspective, and using an add method in the entity for adding items.
One benefit of this is that you can put additional logic in there. For instance in your store example, you could set a 'storesStockedIn' collection (if there was such a thing) in the same method, and so keep all the logic about to creating that relationship in one place.
This isn't really a NHibernate thing, but rather an OOP thing. (Although I'm not familiar with EF - maybe it automates some of this for you). The design decisions are exactly the same as if it was just an unpersisted poco (without NHibernate).