Repository pattern with mvc without entity framework - asp.net

Is repository pattern with unit of work best fit for entity framework application?
I am creating a new asp.net mvc application and i want to use stored procedure (microsoft enterprise library) instead of Entity framework(or any other ORM).
So how can i use repository pattern with mvc application?
I have explored many tutorials but not getting expected result. Please suggest me better approach for n tier application.

You have to understand that "repository pattern" is just an idea to organize your code. I think you can still use it without any problem.
I just want to provide you an example of implementation using sql stored procedure: suppose you have to manage the classic table "Contacts".
You can create your UnitOfWork contract:
public interface IContactsRepository {
void AddContact(Contact c);
void RemoveContact(Contact c);
void UpdateContact(Contact c);
void Search(string keyword);
}
After, you can create your own implementation without using EF:
public sealed class SPContactsRepository : IContactsRepository {
// Is just an exampl.e
public void AddContact(Contact c) {
var sqlCommnad = new SqlCommand(this._connectionString);
sqlCommand.CommandText = "dbo.AddContact";
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.AddParameter("Name", c.Name);
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQuery();
}
}
Hope this can help!

So just to continue what Roberto already started, your controller in the MVC app will look like this:
public class ContactsController : Controller
{
private readonly IContactsRepository _contactsRepo;
public ContactsController(IContactsRepository repo)
{
_contactsRepo = repo;
}
}
These pattern uses dependency injection(DI). There are several options for DI container. You can use Unity which is a Microsoft package that you can install via nuget package manager to your MVC web project. The install will create a UnityConfig.cs file in your App_Start folder. You can register the dependency as:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IContactsRepository, SPContactsRepository>();
}
And in your Global.asax.cs file inside Application_Start(), you initialize the container:
UnityConfig.RegisterComponents();

If you use EF, the DbContext is already your Unit of Work and the DbSet as your repository. Having said that, you should not create a repository that will add another layer of data abstraction. Instead, you can create, domain services.

Related

ASP.NET Core Data Access (EF6, EF Core 1.0)

I have been really excited about using ASP.NET Core 1.0 and can't wait to create some production apps. The one issue I have is the Data Access, using MVC5 and EF6 made it really easy to create an .edmx file and have your Stored Procedures mapped (complex types), a fantastic feature which makes it really easy for us to access data.
EF Core 1.0 github page says that it will implement Stored procedure mapping.
I have seen examples where you write your query but I want to prevent SQL Injection.
What is the best way to call a Stored Procedures with EF6 using .NET Core 1.0 with the full .NET framework?
One possible work around is to use a Class Library which you can add your EF6 ADO.NET Entity Data Model to.
Class Library (DataAccessLayer)
Add your connection string data here
namespace DataAccessLayer
{
public class Class1
{
public static DbConnection GetConnectionString()
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
entityBuilder.Metadata = "res://*/Models.devModel.csdl|res://*/Models.devModel.ssdl|res://*/Models.devModel.msl";
entityBuilder.ProviderConnectionString = "data source=dev-server;initial catalog=ProductWorkflow_New;persist security info=True;user id=user;password=password;MultipleActiveResultSets=True;App=EntityFramework";
entityBuilder.Provider = "System.Data.SqlClient";
return new EntityConnection(entityBuilder.ToString());
}
}
}
devModel.Context.cs (devModel.edmx)
public partial class devModelEntities : DbContext
{
public devModelEntities()
// Add static method here
: base(Class1.GetConnectionString(), true)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
// Your generated code..
}

Why all asp.net mvc samples on the net reference the DAL in UI

may be I got it all wrong but in all the companies I have worked we never added a reference to the Dal in the UI layer (winforms-Web)
I am new to web but a seasoned winform-wcf developer,however I am struggling with the concept of having the dal being referenced in the UI.
In a big team with no proper supervision is a recipe for disaster.
Why not have 2 composition roots
1)WebUI just services classes (not wcf) when using wcf composition root is in there
2)within the services that we inject there the repository.
Am i missing the obvious?
thanks
UPDATED
In all the samples I see they all use DI (Unity-Autofac-Nject etc..) and they wire up the repository via interface,which also requires the concrete class,hence the reference to the DAL.Can this be done in the service layer?
There's a way to inject dependencies without referencing data access layer from the UI. You have to add a transversal Utils or Helpers project that will resolve all dependencies across the project.
In this explanation I'll use Unity for DI. I'll walk your through it in a couple of steps:
First, create an Utils project. This project will be transversal to all the layers. Add this static class with an extension method for IUnityContainer:
// This class will resolve all dependencies across the project
public static class DependencyResolver
{
// This method will resolve all dependencies
public static void ResolveDependencies(this IUnityContainer container)
{
container.ResolveBusinessLayerDependencies();
container.ResolveDataAccessLayerDependencies();
}
}
This will force you to create both methods: ResolveBusinessLayerDependencies and ResolveDataAccessLayerDependencies in the container.
Second, you should go to your business logic project (here, you should be able to access the interfaces and implementations of this layer). Add a new static class like this:
public static class DependencyResolver
{
public static void ResolveBusinessLayerDependencies(this IUnityContainer container)
{
container.RegisterType<IBusinessLayerClass, BusinessLayerClass>();
}
}
Do the same for your data access project:
public static class DependencyResolver
{
public static void ResolveDataAccessLayerDependencies(this IUnityContainer container)
{
container.RegisterType<IDataAccessLayerClass, DataAccessLayerClass>();
}
}
Now in the UnityConfig.cs, the method RegisterTypes would be something like:
public static void RegisterTypes(IUnityContainer container)
{
container.ResolveDependencies();
}
This is one way I've find useful to use DI without referencing all layers from the main project

Referencing in the context of asp.net Identity 2.0 separation

I try to separate one of my API projects into three different layers.
The API
Data access(repos + uow)
Data Entities
The API is using Asp.net Identity 2.0 with code from a sample I installed, just enough to work with OAuth Authorization.
However, When I do this separation, sometimes I get an error telling me that I need to reference the third layer(entities) from my first layer. And I can't figure out why. That would break the whole purpose of the separation, right?
For example, when I try to replace this line(from the API layer in Startup.Auth.cs, ConfigureAuth method)
app.CreatePerOwinContext(ApplicationDbContext.Create);
With
app.CreatePerOwinContext(uow.CreateDbContext())
A method that returns a new instance of the ApplicationDbContext.
I would expect that context to be returned from my second layer, where my UnitOfWork is(which in turn gets the ApplicationDbContext from the data layer).
Could someone please explain how this works?
To solve your issue you need to start use Interfaces and any DI-framework. Here I can provide you with the code if you want to start using AutoFac (https://code.google.com/p/autofac/wiki/WebApiIntegration).
When you installed AutoFac to your solution through Nuget. Add this part of code in your Global.asax.cs file.
protected void Application_Start()
{
...
SetupAutoFac();
...
}
private static void SetupAutoFac()
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Setup();
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
Create this part of code in your BLL-layer:
public static class AutoFacConfiguration
{
public static IContainer Setup(this ContainerBuilder builder)
{
REGISTER ALL YOUR SERVICES AND UOW HERE
return builder.Build();
}
}
After this you can inject every services Interface to your ApiControllers, and the the WebAPi will only have a reference to your BLL-layer or to the layer where you put all your interfaces.

How to get Entity framework to create/update the Database table without saving an object

I'm in the process of adding new fields, on my class but I've noticed the table won't be created until I save an object of that class. It's a bit annoying, is there a way to force it to create that table on App start or something?
You can force the initializer at Application_Start by
protected void Application_Start()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
(new MyContext()).Database.Initialize(true);
}
I think you can use Repository and Unit of Work patterns.
Using Repository and Unit of Work patterns with Entity Framework 4.0
which the Save method is defined in IUnitOfWork interface.
public interface IUnitOfWork
{
void Save();
}

Attach additional ObjectSets to ObjectContext from separate project

I hope this makes sense. I have a ASP.NET web application that uses Entity Framework. I have added a couple of custom tables to the db and created a separate project to handle the CRUD operations for those tables. I chose the separate project because I don't want future upgrades to the application to overwrite my custom features.
My problem is this. How do I attach/combine my custom ObjectContext to the ObjectContext of the application? I want to use the same UnitOfWorkScope (already in the application) to maintain the one ObjectContext instance per HTTP request. Again, I don't want to add my ObjectSets to the application's ObjectContext for my reason listed above.
Here is some code:
Widget.cs
public partial class Widget
{
public Widget()
{
}
public int WidgetId {get;set;}
public string WidgetName {get;set;}
}
WidgetObjectContext.cs
public partial class WidgetObjectContext : ObjectContext
{
private readonly Dictionary<Type, object> _entitySets;
public ObjectSet<T> EntitySet<T>()
where T : BaseEntity
{
var t = typeof(T);
object match;
if(!_entitySets.TryGetValue(t, out match))
{
match = CreateObjectSet<T>();
_entitySets.Add(t, match);
}
return (ObjectSet<T>)match;
}
public ObjectSet<Widget> Widgets
{
get
{
if((_widgets == null))
{
_widgets = CreateObjectSet<Widget>();
}
return _widget;
}
}
private ObjectSet<Widget> _widgets;
In my WidgetManager class if I was using the application's ObjectContext I would query my tables like this:
var context = ObjectContextHelper.CurrentObjectContext;
var query = from c in context.ObjectSet .... etc
What I want would be to do something like this:
var context = ObjectContextHelper.CurrentObjectContext.Attach(WidgetObjectContext);
I know this won't work but that is the gist of what I am trying to accomplish. Hope this is clear enough. Thanks.
I don't think it is possible. ObjectContext creates entity connection which connects to metadata describing mapping and database. But you have to different sets of metadata - one for ASP.NET application and one for separate project. Simply you need two connection to work with these models => you need two ObjectContexts.
FYI: The previous answer was correct at the time of the answer. It is now possible to do this using the DbContext available in EF 4.1. The caveat is that you must use the code-first strategy in order to build your custom context. In other words, you won't be able to use EDMX files to accomplish this.

Resources