patterncsharpMinor
UnitOfWork, removing abstraction of abstraction (Repository)
Viewed 0 times
unitofworkabstractionrepositoryremoving
Problem
I'm creating a small project, but in the past I've used a Repository pattern for it, and it just seemed too bloated. I ended up having repo classes with huge amounts of queries. I'm trying to move away from that. I invite you to critique/help/guide me on my journey to less abstraction:
Note: I like the syntax style of Simple.Data and "Fluentness" of FluentApi. So my naming/style is inspired by them.
I start off with an
My DB Context (pretty standard):
A Query object/service:
Here's my Database Class (name inspired by Simple.Data):
Usage:
This is all fine and good for sim
Note: I like the syntax style of Simple.Data and "Fluentness" of FluentApi. So my naming/style is inspired by them.
I start off with an
IUnitOfWork Interface:public interface IUnitOfWork : IDisposable
{
void Save();
IDbSet Set() where T : class;
}My DB Context (pretty standard):
public partial class MyDbContext : DbContext, IUnitOfWork
{
public MyDbContext() : base("DBConnection") { }
public new IDbSet Set() where T : class
{
return base.Set();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new UsersMap());
}
public void Save()
{
SaveChanges();
}
}A Query object/service:
public class UserService : IService
{
private readonly IUnitOfWork unitOfWork;
public UserService(IUnitOfWork _u)
{
this.unitOfWork = _u;
}
public string GetUserName(string Name)
{
return unitOfWork.Set().Single(s => s.Name == Name).UserName;
}
}Here's my Database Class (name inspired by Simple.Data):
public sealed partial class Database
{
private readonly IUnitOfWork context;
public Database(IUnitOfWork _context = null)
{
if (_context == null)
this.context = new MyDbContext();
else
this.context = _context;
}
public static Database Open()
{
return new Database();
}
// I may move these into a separate file:
public UserService Users { get { return new UserService(context); } }
}Usage:
var userName = Database.Open().Users.GetUserName("John");
Console.WriteLine(userName);This is all fine and good for sim
Solution
I realize you said
my naming/style is inspired by them.
But I would still point out some of your naming conventions which don't align with C#s.
-
Method/Function level variables should be
-
Same as before, and as a note _underscores should only be used for class level variables.
-
Not required, but a common practice is also that you do indeed use underscores for class level variables
Make sure you are disposing(closing) your database object. I presume by the way you have your class setup that when your database object is disposed it will close, in which case I would recommend using the
This ensures that you are always closing your connection in the end.
Be careful when debugging your code, and remember (depending on your db setup) if you pause the debug in your code while the connection is open, you wont be able to use the database. Also if you have any plans to do mulithreading with this you'll want to use locks.
my naming/style is inspired by them.
But I would still point out some of your naming conventions which don't align with C#s.
-
Method/Function level variables should be
camelCase instead of PascalCasepublic string GetUserName(string Name)
public string GetUserName(string name)-
Same as before, and as a note _underscores should only be used for class level variables.
public UserService(IUnitOfWork _u)
public UserService(IUnitOfWork u)-
Not required, but a common practice is also that you do indeed use underscores for class level variables
private readonly IUnitOfWork unitOfWork;
private readonly IUnitOfWork _unitOfWork;Make sure you are disposing(closing) your database object. I presume by the way you have your class setup that when your database object is disposed it will close, in which case I would recommend using the
using keyword. Which would make your above code look more like this in practice.using(var database = Database.Open())
{
var userName = database.Users.GetUserName("John");
var userFirstName = database.Users.GetFirstName("john123");
}This ensures that you are always closing your connection in the end.
Be careful when debugging your code, and remember (depending on your db setup) if you pause the debug in your code while the connection is open, you wont be able to use the database. Also if you have any plans to do mulithreading with this you'll want to use locks.
Code Snippets
public string GetUserName(string Name)
public string GetUserName(string name)public UserService(IUnitOfWork _u)
public UserService(IUnitOfWork u)private readonly IUnitOfWork unitOfWork;
private readonly IUnitOfWork _unitOfWork;using(var database = Database.Open())
{
var userName = database.Users.GetUserName("John");
var userFirstName = database.Users.GetFirstName("john123");
}Context
StackExchange Code Review Q#51364, answer score: 5
Revisions (0)
No revisions yet.