I'm trying to learn some NHibernate after diving into EF4. Is the equivalent of the EF4 ObjectContext (or DbContext) the NHibernate Session?
Specifically, in EF4, you derive from ObjectContext (or DbContext) and your class contains explicit ObjectSet's of each entity, for example:
public class EcommerceContext : ObjectContext {
public ObjectSet<Customer> Customers {get; set;}
public ObjectSet<Product> Products {get; set;}
// etc.
}
In the NHib examples I've seen so far, the Session object isn't used this way. Am I missing something?
If you're using NHibernate 3 it's fairly trivial to implement a data context.
public class YourDataContext
{
public ISession Session { get; private set; }
public YourDataContext(ISession session)
{
Session = session;
}
public IQueryable<Customer> Customers
{
get
{
return Session.Query<Customer>();
}
}
}
The same thing is possible in NHibernate 2 but slightly different. You will need the NHibernate.Linq library which is in the contrib modules.
public class YourDataContext:NHibernateContext
{
public YourDataContext(ISession session)
: base(session){}
public IOrderedQueryable<Customer> Customers
{
get
{
return Session.Linq<Customer>();
}
}
}
I'm guessing since you're asking about a datacontext that you're looking to use Linq, and if that's the case, you should definitely use NH3 as the linq provider is much improved.
It should be noted that a datacontext in EF and a datacontext in NH are going to behave differently because NH does not do objectracking and EF does, among other things. You'll see other differences as you learn about it.
Related
I'm trying to implement an N-tier architecture using repositories and service layer in asp.net mvc application.
A Service object can own multiple repositories to collect all data it needs using the same unit of work.
Controllers call only Service objects and don't know anything about repositories.
Repository example:
public class UsersRepository : IUsersRepository
{
public IEnumerable<User> GetUsers(UsersQuery query)
{
...
}
}
UsersQuery objects incapsulates several options for querying Users, e.g:
public class UsersQuery
{
public bool IncludeDeleted { get; set; }
public Expression<Func<User, object>> OrderBy { get; set; }
//Ans so on...
}
How should I for example pass dynamic OrderBy clause (and other options) to my repository? Of course, it is possible just to pass Query object through the service, but it seems to me not to be the true way, as producing overhead and violating the DRY principle.
Any suggestions? Thanks in advance.
I wrapped Nhibernate session as the following.
public interface IDalSession : IDisposable
{
void MarkForRollBack();
void End();
IDalSession Start();
IDalSession StartWithTransaction();
T Save<T>(T entity);
T CreateQuery<T>(string query);
//ISession GetHibernateSession { get; }
}
I really want to use QueryOver as my main query.
QueryOver API looks impossible to be wrapped because it is huge.
One solution is to use the NHibernate ISession (GetHibernateSession) in all of the places I need to pull data. but it is very ugliy.
What is the workaround here?
How can I wrap QueryOver?
Thanks
Is this what you mean?
public interface IDalSession : IDisposable
{
void MarkForRollBack();
void End();
IDalSession Start();
IDalSession StartWithTransaction();
T Save<T>(T entity);
T CreateQuery<T>(string query);
IQueryOver<T,T> NewQueryOver<T>(); // check me out
//ISession GetHibernateSession { get; }
}
...
public IQueryOver<T,T> NewQueryOver<T>()
{
return Session.QueryOver<T>();
}
You may get some comments about hiding away anything NH from other layers, so for that its fine to be able to pass back a new linq to NH query as its IQueryable:
public virtual IQueryable<T> NewQuery<T>()
{
return Session.Query<T>();
}
but I personally prefer QueryOver API so I wrap my data access into concrete repositories. S#arp architecture does it nice:
Interface
Impl.
We are using Fluent NH with convention based mapping. I have the following:
public class Foo() : Entity
{
public BarComponent PrimaryBar { get; set; }
public BarComponent SecondaryBar { get; set; }
}
public class BarComponent
{
public string Name { get; set; }
}
I have it to the point where it will create the foo table with a single name field. I've tried the following Override and it doesn't work.
public class FooOverride : IAutoMappingOverride<Foo>
{
public void Override(AutoMapping<Foo> mapping)
{
mapping.Component(x => x.PrimaryBar).ColumnPrefix("primary");
mapping.Component(x => x.SecondaryBar).ColumnPrefix("secondary");
}
}
Do I really need to do a full override mapping or can what I have here be made to work somehow?
I ran into this a couple of years ago when I started with FNH. It's one of the few scenarios I've seen where FNH Automapping does not "just work".
The approach that was suggested to me at the time, which I've used successfully (with entities however, not components) is to create empty, intermediate entities, and reference them in the descendant class.
In your case, you could create two new, empty classes that inherit from BarComponent (say, PrimaryBarComponent and SecondaryBarComponent).
Then, in your Foo class, declare them as:
public PrimaryBarComponent PrimaryBar { get; set; }
public SecondaryBarComponent SecondaryBar { get; set; }
This is a kluge, in my opinion, but it works fine with entities and lists of entities, and does not require any overrides or conventions.
I've never used components with FNH, so I don't know if a similar approach will work, but it might be worth investigating.
I ended up getting the way I have described in the question working. It turned out to be a problem with our AutoMappingConfiguration which inherits from DefaultAutomappingConfiguration. We weren't identifying Components properly.
I have the following idea:
Business object implemented as interface or abstract class with certain properties as read only to all layers except the DAL layer. I also want my business objects in another assembly than the DAL (for testing purposes), so marking the properties is not an option for me.
Examples could be one to one relationships or other properties.
I have almost solved the issue by doing the following
abstract class User
{
public virtual long UserId {get; protected set;}
public virtual string Password {get; protected set;}
...
}
In the DAL:
public class DbUser : User
{
internal virtual void SetPassword(string password) {...}
}
I then map this using fluent as
ClassMap<User> {...}
SubclassMap<DbUser> {...}
The problem I get is that fluent tries to create a table named DbUser.
If I skip the SubclassMap and creates a DbUser object and tries to save it I get an "No persister for this object" error.
Is it possible to solve?
You could probably override what is done with Fluent
public class DbUser: IAutoMappingOverride<DbUser>
{
public void Override(AutoMapping<DbUser> mapping)
{
//tell it to do nothing now, probably tell it not to map to table,
// not 100% on how you'd do this here.
}
}
Or you could have an attribute
public class DoNotAutoPersistAttribute : Attribute
{
}
And in AutoPersistenceModelGenerator read for attribute in Where clause to exclude it.
Check would be something like
private static bool CheckPeristance(Type t) {
var attributes = t.GetCustomAttributes(typeof (DoNotAutoPersistAttribute), true);
Check.Ensure(attributes.Length<=1, "The number of DoNotAutoPersistAttribute can only be less than or equal to 1");
if (attributes.Length == 0)
return false;
var persist = attributes[0] as DoNotAutoPersistAttribute;
return persist == null;
}
Then it kind of depends how you're adding entities but you're probably adding via assembly so this might do it for you:
mappings.AddEntityAssembly(typeof(User).Assembly).Where(GetAutoMappingFilter);
....
...
private static bool GetAutoMappingFilter(Type t)
{
return t.GetInterfaces().Any(x => CheckPeristance(x)); //you'd probably have a few filters here
}
I'm fairly new to NHibernate and have run into a strange inheritance chaining issue with my repository classes. I've been using Gabriel Schenker's FAQ as a reference, and following his examples I've been creating interfaces to define contracts for DAO operations in "repository" classes. The data schema I'm working with is rather extensive, and after a little while I found myself duplicating a lot of code. Specifically, the Add, Update, Delete, and "GetByID" methods were exactly the same after I added a generic "EntityType" parameter to the base interface. So, for example, this would be the most basic interface for repository operations:
public interface IBasicRepository<EntityType> where EntityType : class
{
void Add(EntityType entity);
void Remove(EntityType entity);
void Update(EntityType entity);
EntityType GetByID<IDType>(IDType id);
}
I'll just talk about the Add method from now on, for the sake of brevity. With the generic EntityType, the implementations were all the same:
public void Add(EntityType entity)
{
using (ISession session = NHUtility.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(entity);
transaction.Commit();
}
}
}
Obviously, typing this same method body repeatedly (with the slight change of type) isn't only annoying, it's bad design in my book. So I created an abstract base class I'll call RepositoryBase which provides the implementation for Add(). Since I'm using an abstract instead of an interface, I "break the interface chain" for classes inheriting from RepositoryBase and am forced to make any derivation abstract as well, even though it seems more "correct" to use an interface. Using this crappy little entity example....
public class Entity1
{
public Guid ID { get; set; }
public String Name { get; set; }
}
...one can't do this...
public interface IEntity1Repository : RepositoryBase<Entity1>
{
//Illegal!!!! Bad, naughty programmer!
}
...but this is fine....
public abstract class Entity1RepositoryBase : RepositoryBase<Entity1>
{
public abstract ICollection<Entity1> GetByName(string name);
}
This just bothers me. It works, but it rubs me the wrong way, especially as the chain of inheritance/implementation with this particular schema could go quite deep. So I guess my questions are:
Am I just being stupid and anal retentive about this?
Is there a different/better design that I should be looking at here? I've looked at some other examples (notably Billy McCafferty's) and Schenker's approach seems simplest for novice NHibernating.
Thanks in advance.
One option could be:
public interface IRepository<T> where T: class
{
void Add(T entity);
void Remove(T entity);
void Update(T entity);
T GetByID<IDType>(IDType id);
}
With a base class that implements that interface. Ie:
public abstract class RepositoryBase<T> : IRepository<T> where T: class
{
...
}
Which is then extended for each type of entity if necessary:
public interface IProductRepository : IRepository<Product>
{
// Add extra methods
}
public class ProductRepository : RepositoryBase<Product>, IProductRepository
{
// Implement extra methods
}