How to customize authentication to my own set of tables in asp.net web api 2? - asp.net-web-api

In the default AccountController created I see
public AccountController()
: this(Startup.UserManagerFactory(), Startup.OAuthOptions.AccessTokenFormat)
{
}
In Startup.Auth.cs I see
UserManagerFactory = () =>
new UserManager<IdentityUser>(new UserStore<IdentityUser>());
Seems like the implementation of UserStore comes from Microsoft.AspNet.Identity.EntityFramework.
So, to customize the authentication do I have to implement my own version of UserStore like
class MYSTUFFUserStore<IdentityUser> : UserStore<IdentityUser>
{
}
and override the methods and then do this in Startup.Auth.cs
UserManagerFactory = () =>
new UserManager<IdentityUser>(new MYSTUFFUserStore<IdentityUser>());
I am looking for a correct way to customize the authentication.

Assuming your table is called AppUser, convert your own AppUser domain object to IUser(using Microsoft.AspNet.Identity) like this
using Microsoft.AspNet.Identity;
public class AppUser : IUser
{
//Existing database fields
public long AppUserId { get; set; }
public string AppUserName { get; set; }
public string AppPassword { get; set; }
public AppUser()
{
this.Id = Guid.NewGuid().ToString();
}
[Ignore]
public virtual string Id { get; set; }
[Ignore]
public string UserName
{
get
{
return AppUserName;
}
set
{
AppUserName = value;
}
}
}
Implement the UserStore object like this
using Microsoft.AspNet.Identity;
public class UserStoreService
: IUserStore<AppUser>, IUserPasswordStore<AppUser>
{
CompanyDbContext context = new CompanyDbContext();
public Task CreateAsync(AppUser user)
{
throw new NotImplementedException();
}
public Task DeleteAsync(AppUser user)
{
throw new NotImplementedException();
}
public Task<AppUser> FindByIdAsync(string userId)
{
throw new NotImplementedException();
}
public Task<AppUser> FindByNameAsync(string userName)
{
Task<AppUser> task = context.AppUsers.Where(
apu => apu.AppUserName == userName)
.FirstOrDefaultAsync();
return task;
}
public Task UpdateAsync(AppUser user)
{
throw new NotImplementedException();
}
public void Dispose()
{
context.Dispose();
}
public Task<string> GetPasswordHashAsync(AppUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
return Task.FromResult(user.AppPassword);
}
public Task<bool> HasPasswordAsync(AppUser user)
{
return Task.FromResult(user.AppPassword != null);
}
public Task SetPasswordHashAsync(AppUser user, string passwordHash)
{
throw new NotImplementedException();
}
}
If you have your own custom password hashing you will also need to implement IPasswordHasher. Below is an example where there is no hashing of the password(Oh no!)
using Microsoft.AspNet.Identity;
public class MyPasswordHasher : IPasswordHasher
{
public string HashPassword(string password)
{
return password;
}
public PasswordVerificationResult VerifyHashedPassword
(string hashedPassword, string providedPassword)
{
if (hashedPassword == HashPassword(providedPassword))
return PasswordVerificationResult.Success;
else
return PasswordVerificationResult.Failed;
}
}
In Startup.Auth.cs replace
UserManagerFactory = () =>
new UserManager<IdentityUser>(new UserStore<IdentityUser>());
with
UserManagerFactory = () =>
new UserManager<AppUser>(new UserStoreService()) { PasswordHasher = new MyPasswordHasher() };
In ApplicationOAuthProvider.cs, replace IdentityUser with AppUser
In AccountController.cs, replace IdentityUser with AppUser and delete all the external authentication methods like GetManageInfo and RegisterExternal etc.

Related

How to use a parameter in a Task-Based DelegateCommand in Prism

Can I use a parameter in a task-based DelegateCommand (Prism.Commands):
(https://prismlibrary.com/docs/commanding.html)
public class ArticleViewModel
{
public DelegateCommand SubmitCommand { get; private set; }
public ArticleViewModel()
{
SubmitCommand = new DelegateCommand<object>(async ()=> await Submit());
}
Task Submit(object parameter)
{
return SomeAsyncMethod(parameter);
}
}
Can I use a parameter in a task-based DelegateCommand?
Sure.
internal class ArticleViewModel : BindableBase
{
public ArticleViewModel()
{
SubmitCommandWithMethodGroup = new DelegateCommand<object>( SomeAsyncMethod );
SubmitCommandWithLambda = new DelegateCommand<object>( async x => { var y = await Something(x); await SomethingElse(y); } );
}
public DelegateCommand<object> SubmitCommandWithMethodGroup { get; }
public DelegateCommand<object> SubmitCommandWithLambda { get; }
}

how to fix Error No DataBase Provider when Everything is okay

When I want to Insert A New Object into the db bellow Error Occured:
No database provider has been configured for this DbContext
Services:
private IConfiguration config;
public Startup(IConfiguration config) => this.config = config;
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlServer().AddDbContext<DataContext>(options => options.UseSqlServer(config["ConnectionStrings:MainConnection"]));
services.AddMvc();
}
DataContext:
public class DataContext:DbContext
{
public DataContext() { }
public DataContext(DbContextOptions<DataContext> options) : base(options) { }
public DbSet<Request> Request { get; set; }
public DbSet<AdminAccept> AdminAccept { get; set; }
public DbSet<Payment> Payment { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
base.OnConfiguring(builder);
}
}
Insert command :
public async Task <int> SaveToStorageAsync()
{
using (DataContext context=new DataContext())
{
context.Request.Add(this);
return await context.SaveChangesAsync();
}
}
however migrations and database created succefully
I solved it finally.
everything is okay but use of using expression cause an error.(I wonder why)
to solving it first of all I removed a using and declare a DataContext as parameter:
public async Task<int> SaveToStorageAsync(DataContext context)
{
context.Request.Add(this);
return await context.SaveChangesAsync();
}
after it initiate constructor in the main controller :
DataContext context;
public HomeController(DataContext context)
{
this.context = context;
}
and finally call function by sending context as a parameter.
hopped you used in your scenarios and good luck
Since you register the DataContext with the constructor receiving a DbContextOptions<DataContext> option.You also need to pass that when you create a DataContext
var optionsBuilder = new DbContextOptionsBuilder<DataContext >();
optionsBuilder.UseSqlServer("Your connection string");
using (DataContext context = new DataContext (optionsBuilder.Options))
{
context.Request.Add(this);
return await context.SaveChangesAsync();
}
I suggest that you could use dbContext by DI in controller which is a more recommended way in asp.net core:
public class StudentsController : Controller
{
private readonly DataContext _context;
public StudentsController(DataContext context)
{
_context = context;
}
public async Task <int> SaveToStorageAsync()
{
_context.Request.Add(this);
return await context.SaveChangesAsync();
}
}
The two ways are included in below link:
https://learn.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext#configuring-dbcontextoptions

Custom Not-Found Route Fires Only Once

I tend to dislike posting dozens of lines of code and assuming the community at large is interested in untangling my mess. In this case I've exercised everything I can think to search on Google, traced through Glimpse, and Firebug/Fiddler, and what I'm left with is an occasionally working behavior, which is particularly annoying to debug. So, I'm calling out for help.
Here's the gist: I've got a series of classes that handle MVC routes that are otherwise not found (and would produce a 404 error) thanks to #AndrewDavey. I'm attempting to intercept the 404 and show data-driven content where any exists. It all works until I refresh the page. The request works on the first load, but it never fires again after that.
If you're bored or have an itch, the entire code block is below.
Setup goes like this:
Add WebActivator via NuGet
In your AppStart folder add a cs file with the code below
Add a "PageContext" connection string to your web.config
Run the app, the default MVC screen shows up
Now add "/abc" to the end of the url (i.e http://localhost/abc)
A cshtml view, stored in the database, will render.
Change the view's markup in the database and reload the page. Notice no change in your browser.
the /abc route assumes you have a record in the database with the following
Path: "~/abc/index.cshtml"
View: "#{ Layout = null;}<!doctype html><html><head><title>abc</title></head><body><h2>About</h2></body></html>"
I've got no idea why the first request works and subsequent requests don't hit break points and serve up stale content.
My suspicions are:
Some voodoo with the VirtualFile
Something cached (but where?)
A misconfigured handler
Thanks for the help - here's the code (as I shamefully tuck my tail for posting this much code).
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using SomeCms;
[assembly: WebActivator.PreApplicationStartMethod(typeof(Sample.Web.App_Start.cms), "PreStart")]
namespace Sample.Web.App_Start
{
public static class cms
{
public static void PreStart()
{
DynamicModuleUtility.RegisterModule(typeof(InstallerModule));
}
}
}
namespace SomeCms
{
class ActionInvokerWrapper : IActionInvoker
{
readonly IActionInvoker actionInvoker;
public ActionInvokerWrapper(IActionInvoker actionInvoker)
{
this.actionInvoker = actionInvoker;
}
public bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (actionInvoker.InvokeAction(controllerContext, actionName))
{
return true;
}
// No action method was found.
var controller = new CmsContentController();
controller.ExecuteCmsContent(controllerContext.RequestContext);
return true;
}
}
class ControllerFactoryWrapper : IControllerFactory
{
readonly IControllerFactory factory;
public ControllerFactoryWrapper(IControllerFactory factory)
{
this.factory = factory;
}
public IController CreateController(RequestContext requestContext, string controllerName)
{
try
{
var controller = factory.CreateController(requestContext, controllerName);
WrapControllerActionInvoker(controller);
return controller;
}
catch (HttpException ex)
{
if (ex.GetHttpCode() == 404)
{
return new CmsContentController();
}
throw;
}
}
static void WrapControllerActionInvoker(IController controller)
{
var controllerWithInvoker = controller as Controller;
if (controllerWithInvoker != null)
{
controllerWithInvoker.ActionInvoker = new ActionInvokerWrapper(controllerWithInvoker.ActionInvoker);
}
}
public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
return factory.GetControllerSessionBehavior(requestContext, controllerName);
}
public void ReleaseController(IController controller)
{
factory.ReleaseController(controller);
}
}
class InstallerModule : IHttpModule
{
static bool installed;
static readonly object installerLock = new object();
public void Init(HttpApplication application)
{
if (installed)
{
return;
}
lock (installerLock)
{
if (installed)
{
return;
}
Install();
installed = true;
}
}
static void Install()
{
Database.SetInitializer(new CreateDatabaseIfNotExists<PageContext>());
HostingEnvironment.RegisterVirtualPathProvider(new ExampleVirtualPathProvider());
WrapControllerBuilder();
AddNotFoundRoute();
AddCatchAllRoute();
}
static void WrapControllerBuilder()
{
ControllerBuilder.Current.SetControllerFactory(new ControllerFactoryWrapper(ControllerBuilder.Current.GetControllerFactory()));
}
static void AddNotFoundRoute()
{
// To allow IIS to execute "/cmscontent" when requesting something which is disallowed,
// such as /bin or /add_data.
RouteTable.Routes.MapRoute(
"CmsContent",
"cmscontent",
new { controller = "CmsContent", action = "CmsContent" }
);
}
static void AddCatchAllRoute()
{
RouteTable.Routes.MapRoute(
"CmsContent-Catch-All",
"{*any}",
new { controller = "CmsContent", action = "CmsContent" }
);
}
public void Dispose() { }
}
public class CmsContentController : IController
{
public void Execute(RequestContext requestContext)
{
ExecuteCmsContent(requestContext);
}
public void ExecuteCmsContent(RequestContext requestContext)
{
//new CmsContentViewResult().ExecuteResult(new ControllerContext(requestContext, new FakeController()));
new CmsContentViewResult().ExecuteResult(new ControllerContext(requestContext, new FakeController()));
}
// ControllerContext requires an object that derives from ControllerBase.
// NotFoundController does not do this.
// So the easiest workaround is this FakeController.
class FakeController : Controller { }
}
public class CmsContentHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var routeData = new RouteData();
routeData.Values.Add("controller", "CmsContent");
var controllerContext = new ControllerContext(new HttpContextWrapper(context), routeData, new FakeController());
var cmsContentViewResult = new CmsContentViewResult();
cmsContentViewResult.ExecuteResult(controllerContext);
}
public bool IsReusable
{
get { return false; }
}
// ControllerContext requires an object that derives from ControllerBase.
class FakeController : Controller { }
}
public class CmsContentViewResult : ViewResult
{
public CmsContentViewResult()
{
ViewName = "index";
}
public override void ExecuteResult(ControllerContext context)
{
var request = context.HttpContext.Request;
if (request != null && request.Url != null)
{
var url = request.Url.OriginalString;
ViewData["RequestedUrl"] = url;
ViewData["ReferrerUrl"] = (request.UrlReferrer != null && request.UrlReferrer.OriginalString != url)
? request.UrlReferrer.OriginalString
: null;
}
base.ExecuteResult(context);
}
}
public class ExampleVirtualPathProvider : VirtualPathProvider
{
private readonly List<SimpleVirtualFile> virtualFiles = new List<SimpleVirtualFile>();
public ExampleVirtualPathProvider()
{
var context = new PageContext();
var pages = context.Pages.ToList();
foreach (var page in pages)
{
virtualFiles.Add(new SimpleVirtualFile(page.Path));
}
}
public override bool FileExists(string virtualPath)
{
var files = (from f in virtualFiles
where f.VirtualPath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase) ||
f.RelativePath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase)
select f)
.ToList();
return files.Count > 0 || base.FileExists(virtualPath);
}
private class SimpleVirtualFile : VirtualFile
{
public SimpleVirtualFile(string filename) : base(filename)
{
RelativePath = filename;
}
public override Stream Open()
{
var context = new PageContext();
var page = context.Pages.FirstOrDefault(p => p.Path == RelativePath);
return new MemoryStream(Encoding.ASCII.GetBytes(page.View), false);
}
public string RelativePath { get; private set; }
}
private class SimpleVirtualDirectory : VirtualDirectory
{
public SimpleVirtualDirectory(string virtualPath)
: base(virtualPath)
{
}
public override IEnumerable Directories
{
get { return null; }
}
public override IEnumerable Files
{
get
{
return null;
}
}
public override IEnumerable Children
{
get { return null; }
}
}
public override VirtualFile GetFile(string virtualPath)
{
var files = (from f in virtualFiles
where f.VirtualPath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase) ||
f.RelativePath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase)
select f).ToList();
return files.Count > 0
? files[0]
: base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return IsPathVirtual(virtualPath) ? null : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
private bool IsPathVirtual(string virtualPath)
{
var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return
virtualFiles.Any(f => checkPath.StartsWith(virtualPath, StringComparison.InvariantCultureIgnoreCase)) ||
virtualFiles.Any(f => checkPath.Replace("~", "").StartsWith(virtualPath, StringComparison.InvariantCultureIgnoreCase));
}
public override bool DirectoryExists(string virtualDir)
{
return IsPathVirtual(virtualDir) || Previous.DirectoryExists(virtualDir);
}
public override VirtualDirectory GetDirectory(string virtualDir)
{
return IsPathVirtual(virtualDir)
? new SimpleVirtualDirectory(virtualDir)
: Previous.GetDirectory(virtualDir);
}
}
public class ContentPage
{
public int Id { get; set; }
public string Path { get; set; }
public string View { get; set; }
}
public class PageContext : DbContext
{
public DbSet<ContentPage> Pages { get; set; }
}
}
This question turns out to be a non-issue. My oversight of the cache dependency in the virtual path provider is returning null for virtual paths. As such, the view is cached indefinitely.
The solution is to use a custom cache dependency provider that expires immediately.
public class NoCacheDependency : CacheDependency
{
public NoCacheDependency()
{
NotifyDependencyChanged(this, EventArgs.Empty);
}
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return IsPathVirtual(virtualPath) ? new NoCacheDependency() : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}

Do not store password in .net membership

I use the built in membership system in a MVC 3 .net application. Later in the developement I will use an external web service for authentication. Hence I would only have to store the (unique) username in the membership system. All other user info can be retrieved through the webservice.
Therefore I wonder how to not store a password?
Don't worry about the storing of the password, just randomly generate and store a password when you create the user.
Have your account controller validate the password against the external webservice in the logon method, if its correct, then simply call FormsAuthentication.SetAuthCookie(userName, false /*persistantCookie*/), which will "login" the user :)
side note:
Have you though about how you will migrate the existing user's to the new external webservice if you only have their password hash/salts?
Not sure if I understand you correctly but I think the best solution to this is writing an custom membership provider. Basically this is just an class with an few functions overriden from the basic membership provider. Here you can implement your own logic for registering, logging in and logging out.
Found an example of an class I used an while back. Just write your own implementation. An other option is to work from your accountcontroller (like haz also mentioned) but I always tend not to implement too much logic into my controllers and let my services handle the business logic.
public class CustomMembershipProvider : MembershipProvider
{
private readonly IGenericService<User> _genericUserService;
public CustomMembershipProvider(IGenericService<User> genericUserService)
{
_genericUserService = genericUserService;
}
public CustomMembershipProvider() : this(new GenericService<User>())
{
}
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
throw new NotImplementedException();
}
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new NotImplementedException();
}
public override string GetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
public override string ResetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override void UpdateUser(MembershipUser user)
{
throw new NotImplementedException();
}
public override bool ValidateUser(string username, string password)
{
try
{
var encodedPassword = password.AsSha512();
var user = _genericUserService.First(u => u.Email == username && u.Password == string.Empty );
return user != null;
}
catch (Exception)
{
return false;
}
}
public override bool UnlockUser(string userName)
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
throw new NotImplementedException();
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
var user = _genericUserService.First(x => x.Email.Equals(username));
var a = new MembershipUser("", user.Firstname, user.Id, user.Email, "", "", true, user.Active,
user.RegisteredOn, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
return a;
}
public override string GetUserNameByEmail(string email)
{
throw new NotImplementedException();
}
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
throw new NotImplementedException();
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override int GetNumberOfUsersOnline()
{
throw new NotImplementedException();
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override bool EnablePasswordRetrieval
{
get { throw new NotImplementedException(); }
}
public override bool EnablePasswordReset
{
get { throw new NotImplementedException(); }
}
public override bool RequiresQuestionAndAnswer
{
get { throw new NotImplementedException(); }
}
public override string ApplicationName
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override int MaxInvalidPasswordAttempts
{
get { throw new NotImplementedException(); }
}
public override int PasswordAttemptWindow
{
get { throw new NotImplementedException(); }
}
public override bool RequiresUniqueEmail
{
get { throw new NotImplementedException(); }
}
public override MembershipPasswordFormat PasswordFormat
{
get { throw new NotImplementedException(); }
}
public override int MinRequiredPasswordLength
{
get { throw new NotImplementedException(); }
}
public override int MinRequiredNonAlphanumericCharacters
{
get { throw new NotImplementedException(); }
}
public override string PasswordStrengthRegularExpression
{
get { throw new NotImplementedException(); }
}
}

Fluent NHibernate Mapping test takes forever

I've recently started to learn Fluent NH, and I'm having some trouble with this test method. It takes forever to run (it's been running for over ten minutes now, and no sign of progress...).
[TestMethod]
public void Entry_IsCorrectlyMapped()
{
Action<PersistenceSpecification<Entry>> testAction = pspec => pspec
.CheckProperty(e => e.Id, "1")
.VerifyTheMappings();
TestMapping<Entry>(testAction);
}
with this helper method (slightly simplified - i have a couple of try/catch blocks too, to provide nicer error messages):
public void TestMapping<T>(Action<PersistenceSpecification<T>> testAction) where T : IEntity
{
using (var session = DependencyFactory.CreateSessionFactory(true).OpenSession())
{
testAction(new PersistenceSpecification<T>(session));
}
}
The DependencyFactory.CreateSessionFactory() method looks like this:
public static ISessionFactory CreateSessionFactory(bool buildSchema)
{
var cfg = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory())
.Mappings(m => m.FluentMappings.AddFromAssembly(typeof(Entry).Assembly));
if (buildSchema)
{
cfg = cfg.ExposeConfiguration(config => new SchemaExport(config).Create(false, true));
}
return cfg.BuildSessionFactory();
}
I've tried debugging, but I can't figure out where the bottleneck is. Why is this taking so long?
I would think it has to do with the way your trying to use the session together with the persistence spec. Make a base test class like the one below that provides you a session; if whole test takes longer than about 3 - 4 seconds max something is wrong.
Cheers,
Berryl
[TestFixture]
public class UserAutoMappingTests : InMemoryDbTestFixture
{
private const string _nickName = "berryl";
private readonly Name _name = new Name("Berryl", "Hesh");
private const string _email = "bhesh#cox.net";
protected override PersistenceModel _GetPersistenceModel() { return new UserDomainAutoMapModel().Generate(); }
[Test]
public void Persistence_CanSaveAndLoad_User()
{
new PersistenceSpecification<User>(_Session)
.CheckProperty(x => x.NickName, _nickName)
.CheckProperty(x => x.Email, _email)
.CheckProperty(x => x.Name, _name)
.VerifyTheMappings();
}
}
public abstract class InMemoryDbTestFixture
{
protected ISession _Session { get; set; }
protected SessionSource _SessionSource { get; set; }
protected Configuration _Cfg { get; set; }
protected abstract PersistenceModel _GetPersistenceModel();
protected PersistenceModel _persistenceModel;
[TestFixtureSetUp]
public void SetUpPersistenceModel()
{
_persistenceModel = _GetPersistenceModel();
}
[SetUp]
public void SetUpSession()
{
NHibInMemoryDbSession.Init(_persistenceModel); // your own session factory
_Session = NHibInMemoryDbSession.Session;
_SessionSource = NHibInMemoryDbSession.SessionSource;
_Cfg = NHibInMemoryDbSession.Cfg;
}
[TearDown]
public void TearDownSession()
{
NHibInMemoryDbSession.TerminateInMemoryDbSession();
_Session = null;
_SessionSource = null;
_Cfg = null;
}
}
public static class NHibInMemoryDbSession
{
public static ISession Session { get; private set; }
public static Configuration Cfg { get; private set; }
public static SessionSource SessionSource { get; set; }
public static void Init(PersistenceModel persistenceModel)
{
Check.RequireNotNull<PersistenceModel>(persistenceModel);
var SQLiteCfg = SQLiteConfiguration.Standard.InMemory().ShowSql();
SQLiteCfg.ProxyFactoryFactory(typeof(ProxyFactoryFactory).AssemblyQualifiedName);
var fluentCfg = Fluently.Configure().Database(SQLiteCfg).ExposeConfiguration(cfg => { Cfg = cfg; });
SessionSource = new SessionSource(fluentCfg.BuildConfiguration().Properties, persistenceModel);
Session = SessionSource.CreateSession();
SessionSource.BuildSchema(Session, true);
}
public static void TerminateInMemoryDbSession()
{
Session.Close();
Session.Dispose();
Session = null;
SessionSource = null;
Cfg = null;
Check.Ensure(Session == null);
Check.Ensure(SessionSource == null);
Check.Ensure(Cfg == null);
}
}

Resources