I have a project that written ASP.NET Boilerplate (assembly version=4.0.2.0).
I want get current transcation object in Application layer. How can I achieve this?
You get current unit of work with using IUnitOfWorkManager.
IUnitOfWorkManager _unitorWorkManager;
//...
[UnitOfWork]
public void Test(){
/*
Your code
*/
_unitOfWorkManager.Current//gives you current unit of work
.SaveChanges();//same thing with transaction.Commit();
}
If your class inherits something like AbpController, BackgroundJob, AbpServiceBase etc..., you can also use CurrentUnitOfWork.
//...
[UnitOfWork]
public void Test(){
/*
Your code
*/
CurrentUnitOfWork.SaveChanges();//same thing with transaction.Commit();
}
You can check https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work for more information.
Edit: I guess it is not possible to get it in application layer directly since it need dbcontext parameter. What about creating a domain service which provides ActiveDbTransaction. You can create an interface for that in *.Core project and define it where you can access to dbcontext
public interface IMyDbContextActiveTransactionProvider
{
/// <summary>
/// Gets the active transaction or null if current UOW is not transactional.
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
IDbTransaction GetActiveTransaction(ActiveTransactionProviderArgs args);
}
Implement it someplace you can access to dbcontext
public class MyDbContextActiveTransactionProvider: IMyDbContextActiveTransactionProvider, ITransientDependency {
private readonly IActiveTransactionProvider _transactionProvider;
public MyDbContextActiveTransactionProvider(IActiveTransactionProvider transactionProvider){
_transactionProvider = transactionProvider;
}
IDbTransaction GetActiveTransaction(ActiveTransactionProviderArgs args){
return _transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(MyDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
}
https://aspnetboilerplate.com/Pages/Documents/Articles/Using-Stored-Procedures,-User-Defined-Functions-and-Views/index.html#DocHelperMethods
Related
I'm trying to catch all SQLExceptions (connection error, timeout, etc) that EF might throw in a single place. I'm using a unit of work pattern with DI so there's no var using = context for example. Calls like .Single or .ToList are used all around the business logic.
Is there any hook or event of class I could overwrite or inject to do this?
Assuming your Unit of Work eventually calls DbContext.SaveChanges(), you can wrap this call with a try-catch.
Another option, which requires some discipline from your development team, is to add two methods in a base BL class: IList<T> MaterializeList<T>(IQueriable<T> query) and T MaterializeSingle<T>(IQueriable<t> query), which will look something like this:
protected IList<T> MaterializeList<T>(IQueriable<T> query) {
try {
return query.ToList();
}
catch {
//your error handling code here
}
}
and
protected T MaterializeSingle<T>(IQueriable<t> query) {
try {
return query.FirstOrDefault();
}
catch {
//your error handling code here
}
}
and then always materialize using these methods.
As a side note, I try to keep my LINQ to Entities queries in my Data Access layer, leaving the Business Logic layer ignorant of the data access technology.
Little bit work to do, but this will help you i think:
Encapsulate you DbContext withing a fake-context and hide your DbSets. You build an new context which will be the context for you business-logic. This one doesn't give access to the DbSets, it shows custom-dbSets to the user. The main work will be to build the fake-context, which needs to have all methods you're using on the real dbSets.
/// <summary>
/// This sould no be used anywhere except in MyDbContext2
/// </summary>
public class MyDbContext : DbContext
{
public DbSet<SomeTableClass> SomeTable { get; set; }
}
/// <summary>
/// This will be your context in the business-logic
/// </summary>
public class MyDbContext2
{
private MyDbContext realDb;
public MyDbContext2(string conStr)
{
realDb = new MyDbContext();
}
public MyDbSet<SomeTableClass> SomeFakeTable { get; set; }
}
/// <summary>
/// Fake-set with logging
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyDbSet<T> where T : class
{
private DbSet<T> dbSet;
public MyDbSet(DbSet<T> realDbSet)
{
this.dbSet = realDbSet;
}
public List<T> ToList()
{
try
{
return dbSet.ToList();
}
catch (Exception e)
{
// Do some logging..
throw;
}
}
public T SingleOrDefault()
{
try
{
return dbSet.SingleOrDefault();
}
catch (Exception e)
{
// Do some logging..
throw;
}
}
}
A good idea would be to rename you DbContext and introduce a the fake-one with the old name. This way Visual Studio will show you which methods you have to implement.
So I have a typical three tiered application layered as below
DAL -> Repository -> Business -> Web.UI/API
I have been reading this article about registering dependencies by centralizing them via modules.
The web layer only has a reference to Business which only has a reference to the Repo which only has a reference to the lowest DAL layer. In this topology since the UI/API layer knows nothing about the Repository and has no reference to it, I can't register the modules in the Repository in the UI/API layer. Similarly I can't register the modules present in the DAL in the Business layer. What I want to do is start the registration process in the top most layer which then sets off a cascading effect of registrations in subsequent layers.
Typically what this would look like is each layer exposing a RegisterAllModules method and somehow trigger the RegisterAllModules method from the layer below it. Has something like this been done? Or is there another way to do this? At this point I don't know if I should roll my own logic out as I mentioned here above, since I don't know if there is a documented way to do something like this or not. Thoughts on how to best go forward here is what I am looking for.
Thanks.
Mmmm... I don't know if what follows is a proper response, but I'm going to try to give you the tools for a solution that suits your exact requirementes.
have you looked into json/xml module configuration? You do not need to know the assemblies through cross reference, you just need to know the name of the assemblies in app.config (or web.config). E.g: you can register one module for Repositories in the Repo assembly and one module for Business services in the Business.dll. This completely removes the need of cross-referencing the various assemblies (for Module scanning, you will still need references for method calls, but that is expected anyway). See here for details: http://docs.autofac.org/en/latest/configuration/xml.html#configuring-with-microsoft-configuration
if you want to enforce no call is done from (say) UI to Repo, you can leverage the "Instance Per Matching Lifetime Scope" function (see http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-matching-lifetime-scope). You can use that registration method in order to enforce a Unit-of-work approach. E.g: a Repository can only be resolved in a "repository" LifetimeScope, and only Business components open scopes tagged "repository".
an alternative approach to tagged scopes is in using the "Instance per Owned<>" pattern. In this way, each Business service would require an Owned<Repository>.
Something like:
var builder = new ContainerBuilder();
builder.RegisterType();
builder.RegisterType().InstancePerOwned();
AFAICT, a correct approach would be to register the components through Modules, referenced by the Json/Xml config, and each Module should target specific LifetimeScopes.
When you a class calls the underlying layer, it should open a new LifetimeScope("underlying layer").
I will elaborate further, if you want advice on implementation strategies.
Best,
Alberto Chiesa
Edit:
I didn't knew the "composition root" meaning. Well, thanks for the info!
I favor a SIMPLE configuration file (be it the .config file or a separate .json or .xml file), because I feel that a list of modules to be imported is simpler done through a list than through a class. But this is opinion.
What is not an opinion is that you can import modules from assembly that are not referenced by the "Composition Root" assembly, in a simple and tested way.
So, I would go for Modules for every component registration, but for a textual configuration file for Module registration. YMMV.
Now, let me show you an example of the Unit of Work pattern that I'm using in many live projects.
In our architecture we make heavy use of a Service Layer, which holds responsibility for opening connections to the db and disposing them when finished, etc.
It's a simpler design than what you're after (I prefer shallow other than deep), but the concept is the same.
If you are "out" of the Service Layer (e.g. in an MVC Controller, or in the UI), you need a ServiceHandle in order to access the Service layer. The ServiceHandle is the only class that knows about Autofac and is responsible for service resolution, invocation and disposal.
The access to the Service Layer is done in this way:
non service classes can require only a ServiceHandle
invocation is done through _serviceHandle.Invoke(Func)
Autofac injects the ready to use handles via constructor injection.
This is done through the use of BeginLifetimeScope(tag) method, and registering services (in a module) in this way:
// register every service except for ServiceBase
Builder.RegisterAssemblyTypes(_modelAssemblies)
.Where(t => typeof(IService).IsAssignableFrom(t) && (t != typeof(ServiceBase)))
.InstancePerDependency();
// register generic ServiceHandle
Builder.RegisterGeneric(typeof(ServiceHandle<>))
.AsSelf()
.AsImplementedInterfaces()
.InstancePerDependency();
And registering every shared resource as InstancePerMatchingLifetimeScope("service")
So, an example invocation would be:
... in the constructor:
public YourUiClass(ServiceHandle<MyServiceType> myserviceHandle)
{
this._myserviceHandle = myserviceHandle;
}
... in order to invoke the service:
var result = _myserviceHandle.Invoke(s => s.myServiceMethod(parameter));
This is the ServiceHandle implementation:
/// <summary>
/// Provides a managed interface to access Model Services
/// </summary>
/// <typeparam name="TServiceType">The Type of the parameter to be managed</typeparam>
public class ServiceHandle<TServiceType> : IServiceHandle<TServiceType> where TServiceType : IService
{
static private readonly ILog Log = LogManager.GetLogger(typeof(ServiceHandle<TServiceType>));
private readonly ILifetimeScope _scope;
/// <summary>
/// True if there where Exceptions caught during the last Invoke execution.
/// </summary>
public bool ErrorCaught { get; private set; }
/// <summary>
/// List of the errors caught during execution
/// </summary>
public List<String> ErrorsCaught { get; private set; }
/// <summary>
/// Contains the exception that was thrown during the
/// last Invoke execution.
/// </summary>
public Exception ExceptionCaught { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="scope">The current Autofac scope</param>
public ServiceHandle(ILifetimeScope scope)
{
if (scope == null)
throw new ArgumentNullException("scope");
_scope = scope;
ErrorsCaught = new List<String>();
}
/// <summary>
/// Invoke a method to be performed using a
/// service instance provided by the ServiceHandle
/// </summary>
/// <param name="command">
/// Void returning action to be performed
/// </param>
/// <remarks>
/// The implementation simply wraps the Action into
/// a Func returning an Int32; the returned value
/// will be discarded.
/// </remarks>
public void Invoke(Action<TServiceType> command)
{
Invoke(s =>
{
command(s);
return 0;
});
}
/// <summary>
/// Invoke a method to be performed using a
/// service instance provided by the ServiceHandle
/// </summary>
/// <typeparam name="T">Type of the data to be returned</typeparam>
/// <param name="command">Action to be performed. Returns T.</param>
/// <returns>A generically typed T, returned by the provided function.</returns>
public T Invoke<T>(Func<TServiceType, T> command)
{
ErrorCaught = false;
ErrorsCaught = new List<string>();
ExceptionCaught = null;
T retVal;
try
{
using (var serviceScope = GetServiceScope())
using (var service = serviceScope.Resolve<TServiceType>())
{
try
{
retVal = command(service);
service.CommitSessionScope();
}
catch (RollbackException rollbackEx)
{
retVal = default(T);
if (System.Web.HttpContext.Current != null)
ErrorSignal.FromCurrentContext().Raise(rollbackEx);
Log.InfoFormat(rollbackEx.Message);
ErrorCaught = true;
ErrorsCaught.AddRange(rollbackEx.ErrorMessages);
ExceptionCaught = rollbackEx;
DoRollback(service, rollbackEx.ErrorMessages, rollbackEx);
}
catch (Exception genericEx)
{
if (service != null)
{
DoRollback(service, new List<String>() { genericEx.Message }, genericEx);
}
throw;
}
}
}
catch (Exception ex)
{
if (System.Web.HttpContext.Current != null)
ErrorSignal.FromCurrentContext().Raise(ex);
var msg = (Log.IsDebugEnabled) ?
String.Format("There was an error executing service invocation:\r\n{0}\r\nAt: {1}", ex.Message, ex.StackTrace) :
String.Format("There was an error executing service invocation:\r\n{0}", ex.Message);
ErrorCaught = true;
ErrorsCaught.Add(ex.Message);
ExceptionCaught = ex;
Log.ErrorFormat(msg);
retVal = default(T);
}
return retVal;
}
/// <summary>
/// Performs a rollback on the provided service instance
/// and records exception data for error retrieval.
/// </summary>
/// <param name="service">The Service instance whose session will be rolled back.</param>
/// <param name="errorMessages">A List of error messages.</param>
/// <param name="ex"></param>
private void DoRollback(TServiceType service, List<string> errorMessages, Exception ex)
{
var t = new Task<string>
service.RollbackSessionScope();
}
/// <summary>
/// Creates a Service Scope overriding Session resolution:
/// all the service instances share the same Session object.
/// </summary>
/// <returns></returns>
private ILifetimeScope GetServiceScope()
{
return _scope.BeginLifetimeScope("service");
}
}
Hope it helps!
I have a somewhat simple web app, that uses an ASMX web service as its sole data access. All the information is gotten from it, and saved to it. It works fine so thats out of the way.
I just updated to VS2012, and it complained about the class implementing the service reference, does not inherit from IDisposeable.
After some reading, i am more confused as some solutions are really elaborate, some are simple. Short version is, after understanding so little, it seems like i cant adapt it to how my app is made.
I have several data access classes, all focusing on methods for an area. For example, one dataaccess for customer related calls, one for product related calls etc.
But since they are all using the same service, they all derive from a base data access class that holds the reference.
This is the base data access class:
public class BaseDataAccess
{
private dk.odknet.webudv.WebService1 _service;
private string _systemBrugerID, _systemPassword;
public BaseDataAccess()
{
//Gets the system user and password that is stored in the webconfig file. This means you only have to change
//the username and password in one place without having to change the code = its not hardcoded.
_systemBrugerID = System.Configuration.ConfigurationManager.AppSettings["SystemBrugerID"].ToString();
_systemPassword = System.Configuration.ConfigurationManager.AppSettings["SystemPassword"].ToString();
_service = new dk.odknet.webudv.WebService1();
}
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get { return _service; }
}
/// <summary>
/// Gets the system user id, used for certain methods in the webservice.
/// </summary>
protected string SystemBrugerID
{
get { return _systemBrugerID; }
}
/// <summary>
/// Gets the system user password, used for certain methods in the webservice.
/// </summary>
protected string SystemPassword
{
get { return _systemPassword; }
}
}
And here is how a derived class utilizes the service reference from the base class:
public class CustomerDataAccess : BaseDataAccess
{
public CustomerDataAccess() {}
/// <summary>
/// Get's a single customer by their ID, as the type "Kunde".
/// </summary>
/// <param name="userId">The user's username.</param>
/// <param name="customerId">Customer's "fkKundeNr".</param>
/// <returns>Returns a single customer based on their ID, as the type "Kunde".</returns>
public dk.odknet.webudv.Kunde GetCustomerById(string userId, string customerId)
{
try
{
return Service.GetKunde(SystemBrugerID, SystemPassword, userId, customerId);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}}
So how on earth do i implement IDisposable in this situation? I just cant wrap my head around it.
EDIT
I have fiddled with the service reference, and come up with this:
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get
{
try
{
using (_service = new dk.odknet.webudv.WebService1())
{
return _service;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
}
Yes the exception handling isnt great, i will get to that (advice is appreciated), but VS2012 does not complain about the lack of IDisposable anymore.
Instantiation of the service has been removed from the constructor. The app works fine without any further modifications.
Will this suffice?
First of all I wanted to thank all of you for your continuous contributions to the Stack Overflow community! I've been a member of Stack Overflow for years and have come to rely on your input more so than any other source online. Though I try to participate and answer members' questions whenever I can, every once in a while I find myself stuck and in need of help.
Speaking of which I have an unusual code problem. I am writing an API library in C# that needs to be able to be called from WPF/Windows Forms application, but also from within Unit Test code.
The issue is that I need to be able to report (in Excel) on whether each method of the library executed properly when the API is called from within a WPF/windows forms application, along some other metadata and optionally a return type.
When the code is consumed within Unit Tests I don't really care about the reporting, but I do need to be able to produce an Assert on whether the API call executed properly or not.
For instance, if in a Unit Test we have an Test Initialize portion, one of the API calls may be to create a Domain User for the test method to use. Another one may also create a Domain Group, so that the user has proper group membership.
To accomodate the consumption of the API from WPF/WinForms, I've been rewriting every function in the API to return a OperationStep type, with the hopes that when all API calls have executed I would have an IEnumerable<OperationStep> which I can write to a CSV file.
So the question is is there an easier way of achieving what I have done so far? The reporting is extremely tedious and time consuming to code, considering that the API library consists of hundreds of similar methods. Samples are described bellow:
OperationStep<PrincipalContext> createDomainConnectionStep = DomainContext.Current.GetPrincipalContext(settings.DomainInfo);
OperationStep<UserPrincipal> createDomainUserStep = DomainContext.Current.CreateUser(createDomainConnectionStep.Context, settings.TestAccountInfo.Username, settings.TestAccountInfo.Password);
OperationStep<GroupPrincipal> createDomainGroupStep = DomainContext.Current.CreateGroup(createDomainConnectionStep.Context, settings.TestAccountInfo.UserGrupName);
Where the DomainContext is a singleton object whose functionality is to connect to the domain controller and create a user, group, and associate the user to a group.
Note that both the second and the third method call require the output of the first, and therefore warranting the need for having the public T Context within the OperationResult object as described bellow.
The OperationStep object consists of the following properties which are inherited by the IOperation interface with the exception of the public T Context.
public class OperationStep<T> : IOperation
{
/// <summary>
/// Denotes the Logical Name of the current operation
/// </summary>
public string Name { get; set; }
/// <summary>
/// Denotes the stage of execution of the current operation: Setup, Execution, Validation, Cleanup
/// </summary>
public OperationStage Stage { get; set; }
/// <summary>
/// Denotes whether the test step completed properly or failed.
/// </summary>
public OperationResult Result { get; set; }
/// <summary>
/// Denotes the return type of the test method.
/// </summary>
public T Context { get; set; }
/// <summary>
/// Denotes any other relevant information about the test step
/// </summary>
public string Description { get; set; }
/// <summary>
/// If the test step result is failed, this should have the stack trace and the error message.
/// </summary>
public string Error { get; set; }
}
The method calls themselves are a bit bloated and tedious but here is a sample.
public class DomainContext
{
private static volatile DomainContext currentContext;
private static object synchronizationToken = new object();
/// <summary>
/// default ctor.
/// </summary>
private DomainContext() { }
/// <summary>
/// Retrieves the Current DomainContext instance.
/// </summary>
public static DomainContext Current
{
get
{
if (currentContext == null)
{
lock (synchronizationToken)
{
if (currentContext == null)
{
currentContext = new DomainContext();
}
}
}
return currentContext;
}
}
/// <summary>
/// Establishes a connection to the domain.
/// </summary>
/// <param name="domainInfo"></param>
/// <returns></returns>
public OperationStep<PrincipalContext> GetPrincipalContext(DomainInfo domainInfo)
{
OperationStep<PrincipalContext> result = new OperationStep<PrincipalContext>();
result.Name = "Establish Connection to Active Directory";
result.Result = OperationResult.Success;
result.Stage = OperationStage.Setup;
result.Description = string.Format("Domain Name: {0}, Default Containter: {1}", domainInfo.FQDN, domainInfo.Container);
try
{
ContextType contextType = this.GetContextType(domainInfo.DomainType);
PrincipalContext principalContext;
try
{
principalContext = new PrincipalContext(contextType, domainInfo.FQDN, domainInfo.Container);
}
catch
{
throw new Exception("Unable to establish connection to Active Directory with the specified connection options.");
}
if (principalContext != null)
{
bool authenticationResult = principalContext.ValidateCredentials(domainInfo.Username, domainInfo.Password);
if (!authenticationResult)
{
throw new Exception("Unable to authenticate domain admin user to Active Directory.");
}
result.Context = principalContext;
result.Result = OperationResult.Success;
}
}
catch(Exception ex)
{
result.Error = ex.Message;
result.Result = OperationResult.Failure;
}
return result;
}
}
When all method calls have executed theoreticaly I should have an IEnumerable<IOperation> which in the case of a win form I can write in a csv file (to be viewed in MS Excel) or in the case of a unit test I can simply omit the extra info and ignore (other than the method executed successively and the T Context property).
If I understood you correctly - all that OperationSteps are here only for logging. Then why not enable simple .NET logging? Log needed info where it is convenient for you. You can use TraceSource with DelimetedTraceListener to write to .csv file. More than that. You can move logging logic to Strategy class and override its logging methods in your unit test so that instead of logging you call Assert methods.
I know the question of session management has been brought up in the past, but I could not find anything that helps me overcome my problem..
I have a number of repository classes (e.g CustomerRepository, ProductRepository etc.) which I resolve through Castle Windsor (Note: I am trying to apply the three calls pattern as outlined here). I figure I'd best have a session per Presenter (in my case, this is equivalent to one per form), however, the repository classes need to access the session for the currently active form.. I am not sure how I incorporate this with the fact that these repositories are resolved through windsor, since presenters are not singletons..
For example:
public class SomePresenter
{
private ISomeView view;
private ISession session;
private ICustomerRepository customerRepository;
private IOrderRepository orderRepository;
public SomePresenter(ISomeView view, ISessionFactory sessionFactory, ICustomerRepository customerRepository, IOrderRepository orderRepository)
{
this.view = view;
this.session = sessionFactory.OpenSession();
this.customerRepository = customerRepository;
this.orderRepository = orderRepository;
}
}
The repositories needs access to the session... How do I go about this using Windsor? Am I forced to manually set the session on the repositories through a property, or is there a clever Windsor trick that I'm unfamiliar with?
Why not just inject an ISession into your repositories instead of an ISessionFactory?
Here is the similar code that I use with Autofac, a different IoC container:
containerBuilder
.Register(c => NHibernateContext.GetSessionFactory().OpenSession())
.As<ISession>()
.InstancePerLifetimeScope();
where NHibernateContext is my one and only static class that configures NHibernate and holds onto an ISessionFactory singleton.
So my repository/lookup object asks for a session:
public MyRepository(ISession session)
{
this.session = session;
}
Then my Presenter/View Model/Superivsing Controller/Whatever-The-Heck-We're-Calling-It-This-Month just gets the repository or lookup object:
public MyPresenter(IWhateverRepository repository)
{
// Look ma, the repository has an ISession and I'm none the wiser!
}
For Windsor, I think (I'm not terribly familiar with its API, you may have to tweak this but it should give you an idea) it would be something like
container.Register(
Component.For<ISession>
.UsingFactoryMethod(
x => x.Resolve<ISessionFactory>().OpenSession())
.LifeStyle.Transient);
That is, you tell the container, "When somebody asks for an ISession, run this little delegate that gets the ISessionFactory and opens a session, then give them that ISession instance."
But who closes the ISession? It's up to you: you could have the repository explicitly close the ISession in its own Dispose() method. Or you could rely on your container to do the closing and disposing; in Autofac, I do this with ILifetimeScope and InstancePerLifetimeScope(); in Windsor, I believe you need to look up nested containers, such that when you dispose a child container, all of the components it created are also disposed.
In my experience, this usually means that the container leaks into at least the "main form" of my application: when it's time to create a form, it creates a new lifetime scope/nested container and shows the form. But nothing below this level knows about the container; it's just to throw a lasso around a set of components and say "get rid of all of these when the form is closed."
(This is to prevent just one big honking ISession from being used throughout most of the application. That works fine in ASP.NET, one session per request, but in Windows Forms, as you note, it is like a ticking time bomb for stale object exceptions. Better for each "unit of work" (typically, each form or service) to have its own ISession.)
You could alternatively design your repositories such that each method requires an ISession to be passed in, but that seems like it'd get tedious.
Hope that gives you some ideas. Good luck!
Why not just have one SessionProvider with individual Data Access Objects (DAO) for each presenter/controller? Your model is accessed through each Data Access Object.
public sealed class SessionProvider
{
static readonly SessionProvider provider = new SessionProvider();
private static NHibernate.Cfg.Configuration config;
private static ISessionFactory factory;
static ISession session = null;
/// <summary>
/// Initializes the <see cref="SessionProvider"/> class.
/// </summary>
static SessionProvider() { }
/// <summary>
/// Gets the session.
/// </summary>
/// <value>The session.</value>
public static ISession Session
{
get
{
if (factory == null)
{
config = new NHibernate.Cfg.Configuration();
config.Configure();
factory = config.BuildSessionFactory();
}
if (session == null)
{
if (config.Interceptor != null)
session = factory.OpenSession(config.Interceptor);
else
session = factory.OpenSession();
}
return session;
}
}
}
public sealed class OrderDataControl
{
private static ILog log = LogManager.GetLogger(typeof(OrderDataControl));
private static OrderDataControl orderDataControl;
private static object lockOrderDataControl = new object();
/// <summary>
/// Gets the thread-safe instance
/// </summary>
/// <value>The instance.</value>
public static OrderDataControl Instance
{
get
{
lock (lockOrderDataControl)
{
if (orderDataControl == null)
orderDataControl = new OrderDataControl();
}
return orderDataControl;
}
}
/// <summary>
/// Gets the session.
/// </summary>
/// <value>The session.</value>
private ISession Session
{
get
{
return SessionProvider.Session;
}
}
/// <summary>
/// Saves the specified contact.
/// </summary>
/// <param name="contact">The contact.</param>
/// <returns></returns>
public int? Save(OrderItems contact)
{
int? retVal = null;
ITransaction transaction = null;
try
{
transaction = Session.BeginTransaction();
Session.SaveOrUpdate(contact);
if (transaction != null && transaction.IsActive)
transaction.Commit();
else
Session.Flush();
retVal = contact.Id;
}
catch (Exception ex)
{
log.Error(ex);
if (transaction != null && transaction.IsActive)
transaction.Rollback();
throw;
}
return retVal;
}