Created
November 15, 2011 05:10
-
-
Save JoshClose/1366219 to your computer and use it in GitHub Desktop.
Setting Up WCF with Multiple Services and Multiple Databases Using NHibernate and Ninject 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using System.ServiceModel; | |
using Wnn.Business.Repositories; | |
using Wnn.Service.Contract.DataContracts; | |
using Wnn.Service.Contract.ServiceContracts; | |
namespace Wnn.Service | |
{ | |
[ServiceBehavior( InstanceContextMode = InstanceContextMode.PerCall )] | |
public class BlogService : IBlogService | |
{ | |
private readonly UserRepository userRepository; | |
private readonly PostRepository postRepository; | |
private readonly TagRepository tagRepository; | |
public BlogService( UserRepository userRepository, PostRepository postRepository, TagRepository tagRepository ) | |
{ | |
this.userRepository = userRepository; | |
this.postRepository = postRepository; | |
this.tagRepository = tagRepository; | |
} | |
public Post GetPostById( int id ) | |
{ | |
return ConvertPost( postRepository.Get( id ) ); | |
} | |
public User GetUserById( int id ) | |
{ | |
return ConvertUser( userRepository.Get( id ) ); | |
} | |
public User GetUserByUserNameAndPassword( string userName, string password ) | |
{ | |
return ConvertUser( userRepository.GetByUserNameAndPassword( userName, password ) ); | |
} | |
public List<Post> GetPosts() | |
{ | |
return ( from p in postRepository.GetAll() | |
select ConvertPost( p ) ).ToList(); | |
} | |
public List<Post> GetPostsFromAuthor( string userName ) | |
{ | |
return ( from p in postRepository.GetAllForUser( userName ) | |
select ConvertPost( p ) ).ToList(); | |
} | |
private static User ConvertUser( Business.Objects.User userData ) | |
{ | |
User user = null; | |
if( userData != null ) | |
{ | |
user = new User | |
{ | |
Email = userData.Email, | |
FirstName = userData.FirstName, | |
Id = userData.Id, | |
LastName = userData.LastName, | |
UserName = userData.UserName, | |
}; | |
} | |
return user; | |
} | |
private static Post ConvertPost( Business.Objects.Post postData ) | |
{ | |
Post post = null; | |
if( postData != null ) | |
{ | |
post = new Post | |
{ | |
Author = postData.Author.UserName, | |
Content = postData.Content, | |
Created = postData.Created, | |
Id = postData.Id, | |
Title = postData.Title, | |
Tags = ( from t in postData.Tags | |
select t.Name ).ToList() | |
}; | |
} | |
return post; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.Remoting.Messaging; | |
using System.ServiceModel; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Dispatcher; | |
using NHibernate; | |
using Ninject; | |
using Wnn.Business; | |
namespace Wnn.Service.Host | |
{ | |
public class NHibernateInstanceProvider : IInstanceProvider | |
{ | |
private const string sessionKey = "ThreadSession"; | |
private const string transactionKey = "ThreadTransaction"; | |
private readonly Type serviceType; | |
private static SessionManager SessionManager | |
{ | |
get { return CallContext.GetData( sessionKey ) as SessionManager; } | |
set { CallContext.SetData( sessionKey, value ); } | |
} | |
private static ITransaction Transaction | |
{ | |
get { return CallContext.GetData( transactionKey ) as ITransaction; } | |
set { CallContext.SetData( transactionKey, value ); } | |
} | |
public NHibernateInstanceProvider( Type serviceType ) | |
{ | |
this.serviceType = serviceType; | |
} | |
public object GetInstance( InstanceContext instanceContext ) | |
{ | |
return GetInstance( instanceContext, null ); | |
} | |
public object GetInstance( InstanceContext instanceContext, Message message ) | |
{ | |
var connectionStringKey = GetConnectionStringKey( serviceType ); | |
var kernel = new StandardKernel( new NinjectSetup( connectionStringKey ) ); | |
SessionManager = kernel.Get<SessionManager>(); | |
Transaction = SessionManager.BeginTransaction(); | |
var instance = kernel.Get( serviceType ); | |
return instance; | |
} | |
public void ReleaseInstance( InstanceContext instanceContext, object instance ) | |
{ | |
try | |
{ | |
Transaction.Commit(); | |
} | |
catch | |
{ | |
Transaction.Rollback(); | |
} | |
finally | |
{ | |
SessionManager.Close(); | |
SessionManager.Dispose(); | |
} | |
} | |
private static string GetConnectionStringKey( Type serviceType ) | |
{ | |
// All of our database connections should | |
// go here. We could also put all of these types | |
// into a config file and load them dynamically. | |
string connectionStringKey; | |
if( serviceType == typeof( BlogService ) ) | |
{ | |
connectionStringKey = "Dashboard"; | |
} | |
else | |
{ | |
throw new Exception( "Service type '{0}' does not match any database connection." ); | |
} | |
return connectionStringKey; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using NHibernate; | |
using Ninject.Modules; | |
using Wnn.Business; | |
namespace Wnn.Service.Host | |
{ | |
public class NinjectSetup : NinjectModule | |
{ | |
private readonly string connectionStringKey; | |
public NinjectSetup( string connectionStringKey ) | |
{ | |
this.connectionStringKey = connectionStringKey; | |
} | |
public override void Load() | |
{ | |
Bind<ISession>() | |
.ToMethod( ctx => SessionFactoryFactory.GetSessionFactory( connectionStringKey ).OpenSession() ) | |
.InSingletonScope(); | |
Bind<SessionManager>() | |
.ToSelf() | |
.InSingletonScope(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using Wnn.Business.Objects; | |
namespace Wnn.Business.Repositories | |
{ | |
public class PostRepository : RepositoryBase<Post> | |
{ | |
public PostRepository( SessionManager sessionManager ) : base( sessionManager ){} | |
public List<Post> GetAllForUser( string userName ) | |
{ | |
return ( from p in SessionManager.Linq<Post>() | |
where p.Author.UserName == userName | |
select p ).ToList(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
namespace Wnn.Business.Repositories | |
{ | |
public abstract class RepositoryBase<T> | |
{ | |
protected SessionManager SessionManager { get; set; } | |
protected RepositoryBase( SessionManager sessionManager ) | |
{ | |
SessionManager = sessionManager; | |
} | |
public T Get( int id ) | |
{ | |
return SessionManager.Get<T>( id ); | |
} | |
public List<T> GetAll() | |
{ | |
return SessionManager.Linq<T>().ToList(); | |
} | |
public void SaveOrUpdate( T obj ) | |
{ | |
SessionManager.SaveOrUpdate( obj ); | |
} | |
public void Delete( T obj ) | |
{ | |
SessionManager.Delete( obj ); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.ServiceModel; | |
namespace Wnn.Service.Host | |
{ | |
public class ServiceHostEngine | |
{ | |
private readonly List<ServiceHost> serviceHosts = new List<ServiceHost>(); | |
public ServiceHostEngine() | |
{ | |
// We can have multiple services listed here. | |
// We could actually have a list of services in a config | |
// file that is dynamically loaded here also. | |
serviceHosts.Add( new ServiceHost( typeof( BlogService ) ) ); | |
} | |
public void Start() | |
{ | |
foreach( var serviceHost in serviceHosts ) | |
{ | |
serviceHost.Open(); | |
} | |
} | |
public void Stop() | |
{ | |
foreach( var serviceHost in serviceHosts ) | |
{ | |
serviceHost.Close(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using FluentNHibernate.Cfg; | |
using NHibernate; | |
namespace Wnn.Business | |
{ | |
public static class SessionFactoryFactory | |
{ | |
private static readonly object locker = new object(); | |
private static readonly Dictionary<string, ISessionFactory> sessionFactories = new Dictionary<string, ISessionFactory>(); | |
public static ISessionFactory GetSessionFactory( string connectionStringKey ) | |
{ | |
ISessionFactory sessionFactory; | |
sessionFactories.TryGetValue( connectionStringKey, out sessionFactory ); | |
// Double check locking is used here because | |
// WCF could have many instances accessing this | |
// code at the same time. | |
if( sessionFactory == null ) | |
{ | |
lock( locker ) | |
{ | |
sessionFactories.TryGetValue( connectionStringKey, out sessionFactory ); | |
if( sessionFactory == null ) | |
{ | |
sessionFactory = Fluently.Configure() | |
.Database( | |
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005.ConnectionString( | |
c => c.FromConnectionStringWithKey( connectionStringKey ) ) | |
.ProxyFactoryFactory( "NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu" ) ) | |
.Mappings( m => m.FluentMappings.AddFromAssembly( typeof( SessionFactoryFactory ).Assembly ) ) | |
.ExposeConfiguration( cfg => cfg.SetProperty( "generate_statistics", "true" ) ) | |
.ExposeConfiguration( cfg => cfg.SetProperty( "adonet.batch_size", "10" ) ) | |
.BuildSessionFactory(); | |
sessionFactories[connectionStringKey] = sessionFactory; | |
} | |
} | |
} | |
return sessionFactory; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Wnn.Business.Objects; | |
namespace Wnn.Business.Repositories | |
{ | |
public class TagRepository : RepositoryBase<Tag> | |
{ | |
public TagRepository( SessionManager sessionManager ) : base( sessionManager ){} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using Wnn.Business.Objects; | |
namespace Wnn.Business.Repositories | |
{ | |
public class UserRepository : RepositoryBase<User> | |
{ | |
public UserRepository( SessionManager sessionManager ) : base( sessionManager ){} | |
public User GetByUserNameAndPassword( string userName, string password ) | |
{ | |
return ( from u in SessionManager.Linq<User>() | |
where u.UserName == userName && password == u.Password | |
select u ).SingleOrDefault(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<system.serviceModel> | |
<extensions> | |
<behaviorExtensions> | |
<add name="nhibernateServiceBehavior" type="Wnn.Service.Host.NHibernateBehaviorExtensionElement, Wnn.Service.Host, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> | |
</behaviorExtensions> | |
</extensions> | |
<behaviors> | |
<serviceBehaviors> | |
<behavior name="nhibernateServiceBehavior"> | |
<nhibernateServiceBehavior /> | |
<serviceMetadata /> | |
</behavior> | |
</serviceBehaviors> | |
<endpointBehaviors> | |
<behavior name="HttpEnableBehavior"> | |
<webHttp/> | |
</behavior> | |
</endpointBehaviors> | |
</behaviors> | |
<services> | |
<service name="Wnn.Service.BlogService" behaviorConfiguration="nhibernateServiceBehavior"> | |
<host> | |
<baseAddresses> | |
<add baseAddress="net.tcp://localhost:8761/Services/" /> | |
</baseAddresses> | |
</host> | |
<endpoint address="Blog" binding="netTcpBinding" contract="Wnn.Service.Contract.ServiceContracts.IBlogService" /> | |
</service> | |
</services> | |
</system.serviceModel> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment