Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing classes from indirectly referenced packages in .NET Core

I am trying to implement basic UoW/Repository pattern with ASP.NET/Entity Framework Core and I have encountered very troubling behavior.

My solution consists of 4 projects in total.

.DAL project, where my entity classes are defined and where my DbContext is defined:

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class ApplicationDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
}

.Facade project, where my IUnitOfWork and IProductRepository are defined:

public interface IUnitOfWork
{
    IProductRepository Products { get; }
}

public interface IProductRepository
{
    string GetName(int id);
}

.Facade.EF project, where my Facade is implemented with EF:

public class UnitOfWork : IUnitOfWork
{
    private ApplicationDbContext _context;
    public IProductRepository Products { get; private set; }

    internal ApplicationDbContext Context { get { return _context; } }

    public UnitOfWork()
    {
        _context = new ApplicationDbContext();
        Products = new ProductRepository(this);
    }
}

public class ProductRepository : IProductRepository
{
    private ApplicationDbContext _context;
    public ProductRepository(UnitOfWork uow)
    {
        _context = uow.Context;
    }
    public string GetName(int id)
    {
        return _context.Products
            .Where(x => x.Id == id)
            .Select(x => x.Name)
            .FirstOrDefault();
    }
}

.DemoApp project where my application code should be. This project should only know about UnitOfWork and UserRepository and not about ApplicationDbContext class.

  • .DAL references Entity Framework 6.1.3.

  • .Facade does not reference anything.

  • .Facade.EF references .DAL project, .Facade project and Entity Framework 6.1.3.

  • .DemoApp references Facade and Facade.EF but NOT Entity Framework 6.1.3. NOR .DAL project. Even though EF assemblies are added to my bin folder on build, EF is not directly referenced by this project.

With .NET Framework 4.6.x., if I try try to code against ApplicationDbContext in DemoApp, it tells me that class is not defined and is not providing me any usings to be added which is expected behavior.

.NET Framework 4.6.x Project

If I attempt to do the same with .NET Core 1.0 RC2 (by using Entity Framework Core), ApplicationDbContext is accessible from .DemoApp without adding direct reference to .DAL project which completely destroys my attempt to hide implementation details.

enter image description here

.DAL project is not directly referenced by .DemoApp project - why am I allowed to see classes from it there?

Is this expected behavior? Is there a way to make .NET Core projects to have the same behavior as .NET Framework 4.6.x projects?

like image 453
Admir Tuzović Avatar asked Jun 22 '16 09:06

Admir Tuzović


2 Answers

I've been struggling with this for months and finally found a way to disable the transitive references of projects in Core.

In the .csproj file for .Facade.EF, you can add PrivateAssets="All" to the ProjectReference to .DAL:

<ItemGroup>
  <ProjectReference Include="..\.DAL\.DAL.csproj" PrivateAssets="All" />
</ItemGroup>

With this setting, projects that reference .Facade.EF no longer reference .DAL too.

In more abstract terms, if you want A to reference B and B to reference C, but don't want A to reference C, add this:

In B.csproj

<ItemGroup>
  <ProjectReference Include="..\C\C.csproj" PrivateAssets="All" />
</ItemGroup>

Source: https://github.com/dotnet/project-system/issues/2313

like image 145
levihassel Avatar answered Oct 14 '22 18:10

levihassel


That is intended behavior. It is called meta-packages and used for example for the NETStandard.Library package to include all libraries of the base class library. I do not think there is a way hiding them.

like image 31
Thomas Avatar answered Oct 14 '22 19:10

Thomas