How can i use custom dbcontext (Audit Log) with sharprepository - dbcontext

I have a custom dbcontext which name is Tracker-enabled DbContext (https://github.com/bilal-fazlani/tracker-enabled-dbcontext).I want to use it for audit log
And how can I implement EFRepository?
I implemented tracker-enabled-context but i cant solve how override sharp repo commit method.
public class HayEntities : TrackerContext
{
static HayEntities()
{
Database.SetInitializer<HayEntities>(null);
}
public HayEntities() : base(HayEntities)
{
this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ValidateOnSaveEnabled = false;
}
public DbSet<Dummy> Dummys{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DummyConfiguration());
} }
}
public class DummyRepository : ConfigurationBasedRepository<DE.Dummy, long>, IDummyRepository
{
private readonly IRepository<DE.Dummy, long> _servisHasarRepository;
public DummyRepository (HayEntities hayEntities, ICachingStrategy<DE.Dummy, long> cachingStrategy = null)
{this.CachingEnabled = false;
_dummyRepository = new EfRepository<DE.Dummy, long>(hayEntities, cachingStrategy);
}
public void UpdateOrCreate() {
//In this area how can override save/commit method
}
}

You will want to tell SharpRepository to use an IoC provider to inject the DbContext. This will take care of getting the proper DbContext for your EfRepository.
If you want to control things based on the configuration and have custom repositories so you can implement your own mehods like UpdateOrCreate() then you would inherit from ConfigurationBasedRepository as you have in the example.
There are more details on setting up IoC with SharpRepository here: http://fairwaytech.com/2013/02/sharprepository-configuration/ (look in the "Entity Framework and Sharing the DbContext" section)
First look on NuGet for SharpRepository.Ioc.* to find the specific IoC you are using. If you are using StructureMap then you would do something like this.
In your StructureMap configuration:
// Hybrid (once per thread or ASP.NET request if you’re in a web application)
For<DbContext>()
.HybridHttpOrThreadLocalScoped()
.Use<HayEntities>()
.Ctor<string>("connectionString").Is(entityConnectionString);
Then you need to tell SharpRepository to use StructureMap by calling this in your startup code:
RepositoryDependencyResolver.SetDependencyResolver(new StructureMapDependencyResolver(ObjectFactory.Container));
After doing these things, then if you use EfRepository then it will know to ask StructureMap for the DbContext.
Now in your example above where you are using ConfigurationBasedRepository, I would suggest setting the caching in the configuration file instead of in code since you are using the configuration to load the repository. Since IoC is handling the DbContext you don't need to do anyhing with that and you can focus on the custom method you want to write.
public class DummyRepository : ConfigurationBasedRepository<DE.Dummy, long>, IDummyRepository
{
public void UpdateOrCreate()
{
// You have access to the underlying IRepository<> which is going to be an EfRepository in your case assuming you did that in the config file
// here you can call Repository.Add(), or Reposiory.Find(), etc.
}
}

Related

RavenDB with Ninject in ASP.NET MVC3

I want to use RavenDB with ninject in my asp.net mvc3 project, Any idea how I have to configure this?
kernel.Bind<Raven.Client.IDocumentSession>()
.To<Raven.Client.Document.DocumentStore>()
.InSingletonScope()
.WithConstructorArgument("ConnectionString", ConfigurationManager.ConnectionStrings["RavenDB"].ConnectionString);
Here's how I do mine:
If you install Ninject with Nuget, you'll get an /App_start/ NinjectMVC3.cs file. In there:
private static void RegisterServices(IKernel kernel)
{
kernel.Load<RavenModule>();
}
Here's the RavenModule class:
public class RavenModule : NinjectModule
{
public override void Load()
{
Bind<IDocumentStore>()
.ToMethod(InitDocStore)
.InSingletonScope();
Bind<IDocumentSession>()
.ToMethod(c => c.Kernel.Get<IDocumentStore>().OpenSession())
.InRequestScope();
}
private IDocumentStore InitDocStore(IContext context)
{
DocumentStore ds = new DocumentStore { ConnectionStringName = "Raven" };
RavenProfiler.InitializeFor(ds);
// also good to setup the glimpse plugin here
ds.Initialize();
RavenIndexes.CreateIndexes(ds);
return ds;
}
}
And for completeness here's my index creation class:
public static class RavenIndexes
{
public static void CreateIndexes(IDocumentStore docStore)
{
IndexCreation.CreateIndexes(typeof(RavenIndexes).Assembly, docStore);
}
public class SearchIndex : AbstractMultiMapIndexCreationTask<SearchIndex.Result>
{
// implementation omitted
}
}
I hope this helps!
I recommend using a custom Ninject Provider to set up your RavenDB DocumentStore. First place this in your code block that registers your Ninject services.
kernel.Bind<IDocumentStore>().ToProvider<RavenDocumentStoreProvider>().InSingletonScope();
Next, add this class that implements the Ninject Provider.
public class RavenDocumentStoreProvider : Provider<IDocumentStore>
{
var store = new DocumentStore { ConnectionName = "RavenDB" };
store.Conventions.IdentityPartsSeparator = "-"; // Nice for using IDs in routing
store.Initialize();
return store;
}
The IDocumentStore needs to be a singleton, but do not make the IDocumentSession a singleton. I recommend that you simply create a new IDocumentSession using OpenSession() on the IDocumentStore instance Ninject gives you whenever you need to interact with RavenDB. IDocumentSession objects are very lightweight, follow the unit-of-work pattern, are not thread-safe, and are meant to be used and quickly disposed where needed.
As others have done, you might also consider implementing a base MVC controller that overrides the OnActionExecuting and OnActionExecuted methods to open a session and save changes, respectively.

ASP.Net MVC 3 - unitOfWork.Commit() not saving anything

I created a web application using ASP.Net MVC 3 and EF 4.1, and I am using the UnitOfWork pattern, but nothing is getting committed to the database. All this is quite new to me, and I don't know where to start to resolve this issue.
I based myself on this post to create my web application:
http://weblogs.asp.net/shijuvarghese/archive/2011/01/06/developing-web-apps-using-asp-net-mvc-3-razor-and-ef-code-first-part-1.aspx
The final code, which can be obtained here also has a service layer and the UnitOfWOrk is being injected into the services.
Instead of using the custom injector based on Unity 2 as they are in that project, I am using Unity.Mvc3.
Here is my IUnitOfWork class:
public interface IUnitOfWork
{
void Commit();
}
And here is my UnitOfWork class:
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory databaseFactory;
private MyProjectContext dataContext;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
this.databaseFactory = databaseFactory;
}
protected MyProjectContext DataContext
{
get { return dataContext ?? (dataContext = databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}
And here is how one of my service class look like:
public class RegionService : IRegionService
{
private readonly IRegionRepository regionRepository;
private readonly IUnitOfWork unitOfWork;
public RegionService(IRegionRepository regionRepository, IUnitOfWork unitOfWork)
{
this.regionRepository = regionRepository;
this.unitOfWork = unitOfWork;
}
...
}
At start-up, my UnitOfWork component is being registered like this:
container.RegisterType<IUnitOfWork, UnitOfWork>();
Now, no matter whether I try to insert, update or delete, no request is being sent to the database. What am my missing here?
UPDATE:
Here is the content of DataContext.Commit():
public class MyProjectContext : DbContext
{
public DbSet<Region> Regions { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
}
And here is databaseFactory.Get():
public interface IDatabaseFactory : IDisposable
{
MyProjectContext Get();
}
UPDATE #2:
Using the debugger, I am noticing that my Region service and controller constructors are getting called once when performing only a select, but they are called twice when performing an update. Is this normal?
Ok, I found the culprit. It has to do with how I was registering my database factory.
Instead of
container.RegisterType<IDatabaseFactory, DatabaseFactory>();
I needed
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new HierarchicalLifetimeManager());
I found the information on this web site:
http://www.devtrends.co.uk/blog/introducing-the-unity.mvc3-nuget-package-to-reconcile-mvc3-unity-and-idisposable
That's an awfully complex implementation of Unit of Work. I actually prefer this one:
http://azurecoding.net/blogs/brownie/archive/2010/09/22/irepository-lt-t-gt-and-iunitofwork.aspx
Much simpler, and much more flexible. Although you do have to work out a few things for yourself.
May just be a typo but in UnitOfWork your private MyProjectContext is called dataContext (lowercase d)
But in your commit method your calling DataContext.Commit. Any chance that's actually calling a static method that you didn't intend to call? More likely a typo but thought I'd point it out.
+1 for an overly complex implementation of UnitOfWork.

Accessing ninject kernel in Application_Start

I am using Ninject and the MVC3 extension installed with nuget. My kernel setup code is in the App_Start/NinjectMVC3.cs file. Everything works great in controllers, but I can't figure out how to (properly) bind interfaces in the Global.asax.cs MvcApplication code.
I ended up using a hack (creating a public NinjectMVC3.GetKernel() method that returns bootstrap.kernel). However, that will be deprecated, and there must be a proper way to do this that I am not seeing.
Here is my code:
public class LogFilterAttribute : ActionFilterAttribute
{
private IReportingService ReportingService { get; set; }
public LogFilterAttribute( IReportingService reportingService )
{
this.ReportingService = reportingService;
}
...
}
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new HandleErrorAttribute() );
filters.Add( new LogFilterAttribute() );
}
...
protected void Application_Start()
{
...
RegisterGlobalFilters( GlobalFilters.Filters );
// NOTE hack:
var kernel = NinjectMVC3.GetKernel();
var logger = kernel.Get<ILogger>();
var bw = new BackgroundWork(logger);
Application["BackgroundWork"] = bw;
bw.Start();
}
}
There are two interfaces I am interested in. The first is just binding an object to a Global variable (the ILogger for the BackgroundWork).
And the second is for an ActionFilter. I read http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/, but I don't see how it plugs into the actual registration (filter.Add).
I don't want to use the Property Inject if I can avoid it.
Any thoughts on the proper way to do this?
Thanks
MVC 3 introduces the DependencyResolver which is populated into a singleton, and the Ninject extension supports it. You could use that in your MvcApplication class if you need it:
protected void Application_Start()
{
// ...
var logger = DependencyResolver.Current.GetService<ILogger>();
}
Now I should point out that it is unnecessary to do this with action filters. In Ninject.MVC3 you are supposed to use the BindFilter syntax, like so:
// Declare empty attribute
public class MyFilterAttribute : FilterAttribute { }
// Dependency module
public class MyModule : NinjectModule
{
public override void Load()
{
// Other bindings
// ...
this.BindFilter<MyActionFilter>(FilterScope.Action, 1)
.WhenControllerHas<MyFilterAttribute>();
}
}
Note that you have to use this because BindFilter is an extension method, and you also have to reference the Ninject.Web.Mvc.FilterBindingSyntax namespace.

Mvc3 - Best practice to deal with data which are required for (almost) all requests?

I am creating an application in mvc3 and wondering how to deal with database data which is required for all application requests, some of them depends on a session, some of them depends on url pattern basically all data is in database.
Like to know best practice
What I do in my applications and consider to be the best practice is to load your common data to the ViewBag on the Controller constructor.
For every project, I have a DefaultController abstract class that extends Controller. So, every controller in the project must inherit from DefaultController, instead of Controller. In that class' constructor, I load all data common to the whole project, like so:
// DefaultController.cs
public abstract class DefaultController : Controller
{
protected IRepository Repo { get; private set; }
protected DefaultController(IRepository repo)
{
Repo = repo;
ViewBag.CurrentUser = GetLoggedInUser();
}
protected User GetLoggedInUser()
{
// your logic for retrieving the data here
}
}
// HomeController.cs
public class HomeController : DefaultController
{
public HomeController(IRepository repo) : base(repo)
{
}
// ... your action methods
}
That way you will always have the logged in user available in your views.
I do the same as #rdumont but with one exception: I create a CommonViewModel which I use to define all common properties that I use.
public class CommonViewModel
{
public string UserName {get;set;}
public string Extension {get;set; }
}
Declare a property in the base controller:
public abstract class BaseController : Controller
{
protected CommonViewModel Commons { get; private set; }
protected virtual void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewBag.Commons = Commons;
}
}
By doing so I get everything almost typed. The only cast that I need to do is to cast ViewBag.Commons to the CommonViewModel.
Best is to avoid ViewBag at all.
See this answer, which details how to use Html.RenderAction() for that purpose:
Best way to show account information in layout file in MVC3
I'd suggest using a base ViewModel class.
So a base class with properties/functions which should be available at any point.

Where to define AutoMapper mappings?

Where in my ASP.NET MVC application should I define my AutoMapper mappings?
Mapper.CreateMap<User, UserViewModel>();
Presently I am defining these in the constructor of a BaseController, which all my Controlllers derive from. Is this the best place?
I think it's kind of late to answer the question, but maybe someone can use my answer.
I use Ninject to resolve dependencies, so I've created Ninject Module for AutoMapper. Here is the code:
public class AutoMapperModule : NinjectModule
{
public override void Load()
{
Bind<IConfiguration>().ToMethod(context => Mapper.Configuration);
Bind<IMappingEngine>().ToMethod(context => Mapper.Engine);
SetupMappings(Kernel.Get<IConfiguration>());
Mapper.AssertConfigurationIsValid();
}
private static void SetupMappings(IConfiguration configuration)
{
IEnumerable<IViewModelMapping> mappings = typeof(IViewModelMapping).Assembly
.GetExportedTypes()
.Where(x => !x.IsAbstract &&
typeof(IViewModelMapping).IsAssignableFrom(x))
.Select(Activator.CreateInstance)
.Cast<IViewModelMapping>();
foreach (IViewModelMapping mapping in mappings)
mapping.Create(configuration);
}
}
As you can see on load it scans assembly for implementaion of IViewModelMapping and then runs Create method.
Here is the code of IViewModelMapping:
interface IViewModelMapping
{
void Create(IConfiguration configuration);
}
Typical implementation of IViewModelMapping looks like this:
public class RestaurantMap : IViewModelMapping
{
public void Create(IConfiguration configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
IMappingExpression<RestaurantViewModel, Restaurant> map =
configuration.CreateMap<RestaurantViewModel, Restaurant>();
// some code to set up proper mapping
map.ForMember(x => x.Categories, o => o.Ignore());
}
}
As mentioned in this answer, AutoMapper has now introduced configuration profiles to organise your mapping configuration.
So for example, you could define a class to set up your mapping configuration:
public class ProfileToOrganiseMappings : Profile
{
protected override void Configure()
{
Mapper.CreateMap<SourceModel, DestinationModel>();
//other mappings could be defined here
}
}
And then define a class to initialise the mappings:
public static class AutoMapperWebConfiguration
{
public static void Configure()
{
Mapper.Initialize(cfg =>
{
cfg.AddProfile(new ProfileToOrganiseMappings());
//other profiles could be registered here
});
}
}
And then finally, call that class in your global.asax Application_Start() to configure those mappings:
protected void Application_Start()
{
...
AutoMapperWebConfiguration.Configure();
}
The code you are referencing looks like AutoMapper, not StructureMap.
If you're using the static Mapper
method, configuration only needs to
happen once per AppDomain. That means
the best place to put the
configuration code is in application
startup, such as the Global.asax file
for ASP.NET applications. Typically,
the configuration bootstrapper class
is in its own class, and this
bootstrapper class is called from the
startup method.
http://automapper.codeplex.com/wikipage?title=Getting%20Started&referringTitle=Home

Resources