14

We have a database where the tables are organized in multiple schemas like Common.User and Product.Order. There are also tables with the same name in different schemas.

Is it somehow possible to use these schemas to organize the DbSet objects within the DBContext?

The best solution for us would be to access the user object like dbcontext.Common.User. Is this possible?

In general, what is the best strategy to work with multiple database schemas in EF Core?

Edit: The question does not target on how to map tables from different schemas (entity.ToTable("User","Common")). It is about organizing the mapped tables according to their schema within the DbContext.

9
  • Possible duplicate of Using Entity Framework 6 with Multiple DB Schemas but using One DBContext Commented Mar 15, 2018 at 8:51
  • @Seididieci Please see Edit. Commented Mar 15, 2018 at 9:10
  • Sorry i misundestood your question... Usually to separate concerns i use several classes and use them as properties of the main one. Then I consume them like MainClass.OtherClass.Property but i doubt that EF will understand it in a DBContext. Commented Mar 15, 2018 at 9:18
  • I have already tried that and the DbSet objects in the sub class were not initialized. Commented Mar 15, 2018 at 9:24
  • Then I think you have two ways: 1) Have multiple DBContext (one per schema) and a wrapping class with a property per context. 2) Use some naming convention for the DbSet properties... Commented Mar 15, 2018 at 9:34

1 Answer 1

0

This code provides a solution for organizing DbSet objects by schemas in a DbContext, corresponding to a multi-schema database structure.

  • Using schemas to organize DbSet:
    • SchemaDbSet, which combines a DbSet with schema information. This allows DbSets to be grouped by schema.
  • Access objects as dbcontext.Common.User
  • Strategy for working with multiple schemas
public interface ISchema
{
    string Name { get; }
}

public class CommonSchema : ISchema
{
    public string Name => "Common";
}

public class ProductSchema : ISchema
{
    public string Name => "Product";
}

public class SchemaDbSet<TEntity, TSchema> where TEntity : class where TSchema : ISchema, new()
{
    private readonly DbContext _context;
    private readonly string _schemaName;

    public SchemaDbSet(DbContext context)
    {
        _context = context;
        _schemaName = new TSchema().Name;
    }

    public DbSet<TEntity> Entities => _context.Set<TEntity>();

    public IQueryable<TEntity> Query => Entities.AsQueryable();
}

public class CommonSchemaDbSets
{
    public SchemaDbSet<User, CommonSchema> User { get; set; }
}

public class ProductSchemaDbSets
{
    public SchemaDbSet<Order, ProductSchema> Order { get; set; }
}

public class MyDbContext : DbContext
{
    public CommonSchemaDbSets Common { get; }
    public ProductSchemaDbSets Product { get; }

    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
        Common = new CommonSchemaDbSets();
        Product = new ProductSchemaDbSets();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().ToTable("User", "Common");
        modelBuilder.Entity<Order>().ToTable("Order", "Product");

        Common.User = new SchemaDbSet<User, CommonSchema>(this);
        Product.Order = new SchemaDbSet<Order, ProductSchema>(this);
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

See the question: "The question does not target on how to map tables from different schemas". This doesn't answer the question. Also, a general remark for later answers: Please don't post code-only answers. The main audience, future readers, will be grateful to see explained why this answers the question instead of having to infer it from the code.
Took into account, as I understand it is an organizational issue
I don't think that dbcontext.Common runs. The context doesn't have a property Common. You can still only call context.Users.
I apologize, during the implementation, I forgot about this moment
OK, that looks like something that should work. Too much wiring, if you ask me, but OK, let people judge for themselves.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.