Entity Framework - infrastructure in WPF/MVVM application - c#

I'm using EF for the first time, in a WPF application, using MVVM pattern. I read a lot of stuff but I couldn't end up with a solution. My problem is how to integrate EF in my app.
The most common way I found is build your own Repository + UnitOfWork. I don't like it. Basically because I already have DbContext and DbSet that can work as unit of work and repository, so why reinvent the wheel?
So I tried to use DbContext directly from view models like this
public class BookCollectionViewModel : ViewModelBase
{
public void LoadCollection()
{
Books.clear();
var books = new List<Book>();
using(var ctx = new DbContext())
{
books = ctx.DbSet<Book>().ToList();
}
books.Foreach(b => Books.Add(b));
}
ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();
}
But I don't like to use DbContext directly from view models, so I built a service layer
public class DbServices
{
public TReturn Execute<TEntity>(Func<IDbSet<TEntity>, TReturn> func)
{
TReturn retVal = default(TReturn);
using(var ctx = new DbContext())
{
retVal = func(ctx.DbSet<TEntity>());
}
return retVal;
}
}
public class BookCollectionViewModel : ViewModelBase
{
private DbServices mDbServices = new DbServices();
public void LoadCollection()
{
Books.clear();
var books = mDbServices.Execute<Book>((dbSet) => return dbSet.ToList());
books.Foreach(b => Books.Add(b))
}
ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();
}
But this way every action is atomic, so when I modify an entity I have to call SaveChanges() every time or loose changes, because DbContext is always disposed. So why not create a class-wide DbContext?
public class DbServices
{
private Lazy<> mContext;
public DbServices()
{
mContext = new Lazy<TContext>(() => {return new DbContext();});
}
public TContext Context { get { return context.Value; } }
public TReturn Execute<TEntity>(Func<IDbSet<TEntity>, TReturn> func)
{
return func(Context.DbSet<TEntity>());
}
}
Unfortunately, this way again doesn't work, because once a dbcontext is created, it is never disposed... So how about explicitly Open/Close the DbContext?
The question is: Where and how should I create/dispose the DbContext? The only thing I'm sure of is that I don't want to rebuild repository and unit of work, since they already exist as DbContext and DbSet...

I'm in the same position. I find that any persistent repository on the client side causes users not to see each others' changes.
Here's a good video explaining why EF is not the same as a repository
https://www.youtube.com/watch?v=rtXpYpZdOzM
Also I found an excellent end-to-end tutorial on WPF,MVVM & EF
http://www.software-architects.com/devblog/2010/09/10/MVVM-Tutorial-from-Start-to-Finish.
In this he exposes the data through a WCF data service and detaches them from the dbcontext straight away.
Hope it helps

Related

Where to initialize DbContext in MVVM

Let's say I'm making an application. For the user interface I decide to go with an Model-View-ViewModel pattern. The UI will access a service layer which will use Entity Framework Core as a replacement for the more traditional repository (I know people have mixed feelings about this, but this is not the point of this question). Preferably the DbContext from EFCore will be injected into the service. Something like this:
public void SomeUserInterfaceMethod()
{
using (var context = new MyContext())
{
var service = new MyService(context);
service.PerformSomeAction();
}
}
Now this isn't so bad at all, but I do have an issue with it. The using (var context = new MyContext()) will be in a lot of places in the code, even in a small application. This means trouble if I want to change the context as well as for testing purposes.
Now I could replace the new MyContext() with a factory method (MyFactory.GetMyContext()), which would make it easier to replace. But what if I want to change the context to a testing one (using another database)?
Is there some more clever way to initialize MyContext which allows both for easy replacement, but also for easy testing?
Honestly, I don't see any problems in using factory method for your purposes.
Easy replacement example:
public class ClassWithSomeUserInterfaceMethod
{
private readonly IDataContextsFactory dataContextsFactory;
public ClassWithSomeUserInterfaceMethod(IDataContextsFactory dataContextsFactory)
{
this.dataContextsFactory = dataContextsFactory;
}
public void SomeUserInterfaceMethod()
{
using (var context = dataContextsFactory.GetDataContext())
{
var service = new MyService(context);
service.PerformSomeAction();
}
}
}
You can pass any class that implements IDataContextsFactory interface in dataContextsFactory.
Easy testing example:
public AnotherDatabaseDataContextFactory : IDataContextsFactory
{
public IDataContext GetDataContext()
{
return new AnotherDataContext();
}
}
[Test]
public void SomeTest()
{
var factory = new AnotherDatabaseDataContextFactory();
var classWithSomeUserInterfaceMethod = new ClassWithSomeUserInterfaceMethod(factory);
classWithSomeUserInterfaceMethod.SomeUserInterfaceMethod();
// Assert.That ...
}
Hope it helps.

ASP.NET MVC guidelines for static classes for database access

The way I am utilising the MVC pattern at the moment in my ASP.NET application (using Entity Framework) is as follows:
1) My Models folder contains all EF entities, as well as my ViewModels
2) I have a Helpers folders where I store classes created for the purposes of the particular application.
3) In my Helpers folder, I have a static class named MyHelper which contains methods that access the DB using EF.
namespace myApp.Helpers
{
public static class MyHelper
{
public static async Task<ProductVM> GetProductAsync(int productId)
{
using (var context = new myEntities())
{
return await context.vwxProducts.Where(x => x.ProductId == productId).Select(x => new ProductVM { A = x.A, B = x.B }).FirstOrDefaultAsync();
}
}
}
}
4) My controllers then call these functions where necessary:
namespace myApp.Controllers
{
public class ProductController : Controller
{
[HttpGet]
public async Task<ActionResult> Index(int productId)
{
var productVM = await MyHelper.GetProductAsync(productId);
return View(productVM);
}
}
}
I usually encounter comments in SO of the type "don't use a static class, static classes are evil, etc". Would this apply in such a scenario? If yes, why? Is there a better 'structure' my app should follow for best practices and for avoiding such pitfalls?
You can't really use a static class for this. Your Entity Framework context should have one and only one instance per request. Your methods here instantiate a new context for each method, which is going to cause a ton of problems with Entity Framework.
The general concept is fine, but your MyHelper class should be a normal class. Add a constructor that takes an instance of your context, and then use a DI container to inject the context into the helper class and the helper class into your controller.
UPDATE
Helper
namespace myApp.Helpers
{
public class MyHelper
{
private readonly DbContext context;
public MyHelper(DbContext context)
{
this.context = context;
}
public async Task<ProductVM> GetProductAsync(int productId)
{
return await context.vwxProducts.Where(x => x.ProductId == productId).Select(x => new ProductVM { A = x.A, B = x.B }).FirstOrDefaultAsync();
}
}
}
Controller
namespace myApp.Controllers
{
public class ProductController : Controller
{
private readonly MyHelper myHelper;
public ProductController(MyHelper myHelper)
{
this.myHelper = myHelper;
}
[HttpGet]
public async Task<ActionResult> Index(int productId)
{
var productVM = await myHelper.GetProductAsync(productId);
return View(productVM);
}
}
}
Then, you just need to set up a DI container to inject everything. The code for that is entirely dependent on which container you end up going with, so I can't really help you further. It's usually pretty straight-forward, though. Just read the docs for the container. You'll want to set the life-time scope of your objects to the request. Again, it's different for different containers, but they'll all have some sort of request-scope.
I was thinking to add comment to ChrisPratt's answer, but it ended being too long, so let me add separate answer.
Basically, this is not a life/death choice. Sure, static methods are not as flexible as classes for db access. But they are not bad per-se. One DbContext per request is a something to aim for. It is not an absolute must. It is kinda like dependency injection - you get more flexibility and in turn increase code complexity.
Look at these three questions and their answers, by taking into account everything they say, I'm sure you'll be able to answer your question yourself:
Why would I use static methods for database access
When to use static classes in C#
One DbContext per web request... why?
EDIT: Chris left good comment on my answer and I've changed answer a bit to take into account what he said.
Your idea is correct and I use it always. But the style is like this:
1) For each entity (i.e User) we have a static class inside Providers folder. In this class we can do general methods (i.e create, Get, GetAll , ..)
public static class Users
{
public static IEnumerable<kernel_Users> GetAll()
{
Kernel_Context db = new Kernel_Context();
return db.kernel_Users;
}
public static kernel_Users Get(int userId)
{
Kernel_Context db = new Kernel_Context();
return db.kernel_Users.Where(c => c.UserId == userId).FirstOrDefault();
}
...
}
2) We have another class that is not static.It is inside Models folder. This is the place that we can access to an instance of the entity :
public partial class kernel_Users
{
[Key]
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
[NotMapped]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public bool Delete(out string msg)
{
...
}
...
}
I use a static class that has the context injected into a static constructor for the purposes of loading a cache of data that rarely changes. And it (should) be thread safe. I hope this helps you, it's very handy in my experience:
public static class StaticCache<T> where T: class
{
private static List<T> dbSet;
public static Dictionary<string, List<T>> cache = new Dictionary<string, List<T>>();
private static readonly object Lock = new object();
public static void Load(DbContext db, string connStr, string tableName)
{
lock (Lock)
{
try
{
if (connStr != null)
{
using (db)
{
dbSet = db.Set<T>().ToList();
cache.Add(tableName, dbSet);
}
}
}
catch { }
}
}
}
void Testit()
{
var context = new YourContextSubClass(connStr);
StaticCache<TableEntity>.Load(context, connstr, "tableEntityNameString");
}

Thread Safe Unit of Work with EntityFramework

I have a Data Layer that uses one Unit of work that is is basically a wrapper of the EnityFramework data context.
With all the async await stuff going around, I thought I'd start trying to use this data layer with some async calls. (I'm new to asynchronous programming in general)
I quickly ran into the problem of "there is already an open data reader associated with this command" errors.
Is there a good way to make my Unit of work thread-safe? Or should I just be creating another instance of it when i'm about to make some calls (in others words..be more careful).
Are there any good resources to check out for doing this?
My few google searches didn't amount to much, so I thought I'd bring this question to SO.
My Uow looks something like this.
public class MyUnitOfWork: IMyUnitOfWork, IDisposable
{
private MyDbContext DbContext { get; set; }
protected IRepositoryProvider RepositoryProvider;
public MyUnitOfWork(IRepositoryProvider repositoryProvider)
{
CreateDbContext();
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
public MyUnitOfWork(IRepositoryProvider repositoryProvider, MyDbContext context)
{
DbContext = context;
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
public void CreateDbContext()
{
DbContext = new MyDbContext();
//Serialization false if we enable proxied entities
DbContext.Configuration.ProxyCreationEnabled = false;
//avoid serilaization trouble
DbContext.Configuration.LazyLoadingEnabled = false;
}
public void Commit()
{
DbContext.SaveChanges();
}
public IRepository<Person> Persons {get { return repositoryProvider.GetRepo<Person>(); } }
public IRepository<SomeOtherEntityType> SomeOtherType {get { return repositoryProvider.GetRepo<SomeOtherEntityType>(); } }
// IDisposable
// ...
}
This article has general guidelines on how to operate with DbContext, regarding lifetime, multithreading, etc.
http://msdn.microsoft.com/en-us/data/jj729737.aspx

Create service layer with mocked data from LINQ DataContext

I'm using LINQ-to-SQL with ASP.NET MVC 4, and as of this moment I have a repository layer which contacts a real database. This is not very good when I want to unit test.
Also there should never be a logic in the repository layer, so this is why I want to mock the LINQ DataContext so I can create a service layer that talks either to the mock DataContext or to the real DataContext.
I see that my LINQ DataContext class inherits DataContext, but there is no interface, so I can't really mock that. I also see that DataContext uses Table<> class and there exists an interface ITable, so I probably could mock that. Also my LINQ DataContext is a partial class, so maybe I could manipulate that in some kind of way?
When I google this, all articles are from 2008 and are outdated.
Can anyone guide me in the right appropriate direction?
Here is an example of what I want to do. I will have seperate service class for each controller.
public class MyServiceClass
{
IDataContext _context;
// Constructors with dependency injection
public MyServiceClass()
{
_context = new MyRealDataContext();
}
public MyServiceClass(IDataContext ctx)
{
_context = ctx;
}
// Service functions
public IEnumerable<ModelClass> GetAll()
{
return _context.ModelClass;
}
public ModelClass GetOne(int id)
{
return _context.Where(s => s.ID == id).SingleOrDefault();
}
}
Although Linq-to-Sql is still supported in .NET 4+, it has been pushed back in favor of Entity Framework. That's probably why you're finding mostly older articles.
Anyway the best way to go is to write your own DataAccess layer-interface, used through your application. You then can have an implementation of that interface that uses your linq-to-sql for production and a mocked implementation for your unit tests.
Use dependency injection to instantiate the actual implementation class.
For creating a mock implementation you do it either manually (Creating a class in your test project that implements the IDataContext interface but returns hard-coded data) or use one of the mocking frameworks around there.
I have not used every one of them but moq was quite nice. Microsoft has now also their framework in Visual Studio 2012 called Fakes, worth looking at.
Example of using moq
var expectedResultList = new List<ModelClass>(){ ... };
var mockDataContext = new Mock<IDataContext>();
mock.Setup(c => c.GetAll()).Returns(expectedResultList);
MyServiceClass service = new MyServiceClass(mockDataContext.Object);
var list = service.GetAll();
Assert.AreEqual(expectedResultList, list);
In this code you set up your mock object so that it will return your expected list when the GetAll method is called.
This way you can easily test your business logic based on different returns from your data access.
Example of IDataContext
public interface IDataContext<T>
{
IEnumerable<T> GetAll();
T GetById(int id);
int Save(T model);
}
public class LinqToSqlDataContext<T> : IDataContext<T>
{
private DataContext context = new DataContext();
public IEnumerable<T> GetAll()
{
// query datacontext and return enumerable
}
public T GetById(int id)
{
// query datacontext and return object
}
public int Save(T model)
{
// save object in datacontext
}
}
public class MyFirstServiceClass
{
private IDataContext<MyClass> context;
public MyFirstServiceClass(IDataContext<MyClass> ctx)
{
this.context = ctx;
}
....
}
public class MySecondServiceClass
{
private IDataContext<MySecondClass> context;
public MyFirstServiceClass(IDataContext<MySecondClass> ctx)
{
this.context = ctx;
}
....
}

test Entity Framework Models

I'm going to test my EF Models. In order to do this I've create IDbContext class. But I don't know how to rewrite my Save and Delete methods, because I don't know how to write
db.Partner.AddObject(obj); How to rewrite these methods?
public interface IDbContext
{
int SaveChanges();
DbSet<Partner> Partner { get; set; }
}
public class PartnerRepository : IPartnerRepository
{
readonly IDbContext _context;
public PartnerRepository()
{
_context = (IDbContext)new VostokPortalEntities();
}
public PartnerRepository(IDbContext context)
{
_context = context;
}
public void Save(Partner obj)
{
using (var db = new VostokPortalEntities())
{
if (obj.PartnerID == 0)
{
db.Partner.AddObject(obj);
}
else
{
db.Partner.Attach(obj);
db.ObjectStateManager.ChangeObjectState(obj, System.Data.EntityState.Modified);
}
db.SaveChanges();
}
}
public void Delete(Partner obj)
{
using (var db = new VostokPortalEntities())
{
db.Partner.Attach(obj);
db.ObjectStateManager.ChangeObjectState(obj, System.Data.EntityState.Deleted);
db.SaveChanges();
}
}
public List<Partner> GetAll()
{
using (var db = new VostokPortalEntities())
{
return db.Partner.OrderByDescending(i => i.PartnerID).ToList();
}
}
}
Is this proper way to test EF Models?
Unit-testing of repositories takes a lot of time and does not give you many benefits. Why? Because repository don't have complex business logic. Usually there is pretty simple calls to underlying data-access API (i.e. ORM). I think it's match better to spend time on writing full-stack acceptance tests, which also will show if your repository do its job.
BTW there is interesting rule Don't Mock what you don't own:
By testing interactions with a mocked version of type we don't own, we
really are not using our test to check for the correct behavior, nor
to drive out a collaborator’s design. All our test is doing is
reiterating our guess as to how the other type works. Sure, it’s
better than no test, but not necessarily by much.

Categories

Resources