Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core without additional repository pattern

There seems to be a certain movement advocating that when we use EF Core we should avoid creating a Repository & Unit of work pattern because EF Core already implement those two and we can leverage this implicit implementation. That would be great because implementing those patterns is not always as straightforward as it would seem.

So here's the problem. When implementing repository the 'classic' way we have a place to put the code that builds our domain objects. Let me explain with an example; we have an Invoice and an InvoiceRow entities. Each Invoice has many InvoiceRows. I included only the navigational property for brevity.

public class Invoice
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public decimal Total { get; set; }
    public List<InvoiceRow> InvoiceRows { get; }
}

public class InvoiceRow
{
    public int Id { get; set; }
    public Invoice Invoice { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal RowPrice { get; set; }
}

Now, my business object is an Invoice with its rows, and this should be the only way to manipulate the invoices. When using 'explicit' repository we would do something like:

public class InvoicesRepo
{
    public AppDbContext AppDbContext { get; private set; }

    public Invoice Find(int id)
    {
        return

        AppDbContext.Invoices.Where(invoice => invoice.Id == id)
                    .Include(nameof(InvoiceRow))
                    .First();
    }
}

This restricts the access to the Invoice to the method [InvoicesRepo].Find(id) that builds the invoice in the way that is expected by the domain logic code.

Is it possible to achieve this with bare EF Core? Maybe working with visibility of DbSets and/or additional features that I don't know? Since this seems to be quite a fundamental functionality of a full-blown repository, if it's not achievable, have I just destroyed the main argument of experts advocating for no (additional) repository when using EF Core?

like image 855
AgostinoX Avatar asked Apr 01 '26 18:04

AgostinoX


1 Answers

Is it possible to achieve this with bare EF Core? Maybe working with visibility of DbSets and/or additional features that I don't know?

Sure, accepting that the DbContext is your repository doesn't mean you can't make design decisions and you have to have use the default DbContext design.

You can add reusable data access code to your DbContext for convenience and consistency, eg methods like:

public Invoice FindInvoice(int id)
{
    this.Invoices.Where(invoice => invoice.Id == id)
                .Include(nameof(InvoiceRow))
                .First();
}

So for code that needs the standard shape of Invoice with InvoiceRows, they call this method. But for code that needs some nonstandard shape, they still can access the DbSets or IQueryable methods and construct a custom query.

You can even eliminate the DbSet properties, to more strongly guide users to use your custom methods, like:

public IQueryable<Invoice> Invoices => this.Invoices.Include(nameof(InvoiceRow));

Then to get Invoices without InvoiceRows a consumer would either add a custom projection to this, something like

  db.Invoices.Where(i => i.CustomerID == custId).Select(i => new InvoiceDTO(i)).ToList();

or access the DbSet

 var invoice = db.Set<Invoice>().Find(invoiceId);

And you can organize the methods on your DbContext by having it implement various interfaces.

like image 180
David Browne - Microsoft Avatar answered Apr 04 '26 07:04

David Browne - Microsoft



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!