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 IUnitOfWork
Interface:
public interface IUnitOfWork : IDisposable
{
void Save();
IDbSet<T> Set<T>() where T : class;
}
My DB Context (pretty standard):
public partial class MyDbContext : DbContext, IUnitOfWork
{
public MyDbContext() : base("DBConnection") { }
public new IDbSet<T> Set<T>() where T : class
{
return base.Set<T>();
}
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<User>().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 simple tasks. But let's say I want to do multiple things whilst the Database connection is open. I could move Database.Open()
to a separate variable then use it like this:
var database = Database.Open();
var userName = database.Users.GetUserName("John");
var userFirstName = database.Users.GetFirstName("john123");
So my question is, am I doing it wrong? Obviously, my main concern is to not open multiple connections to the Database, and use it like a UnitOfWork
.
My other question is about how to handle CRUD. I have IService
there (currently empty) because I was thinking of putting Insert/Update/Delete in there and adding methods to each Service class - BUT, this turns into a type "Repository" which I was trying to avoid. I don't think it's right for me to expose the DbSet<TEntity>()
so I can .Add()
/.Attach()
- so what should I do here?
I'm still at the planning stage of this, so any changes/recommendations are welcome.