Comments (8)
Yeah, there was a bug that I noticed right after I posted my last comment. It should be fixed now, and there's a new package out there. My apologies for that.
This might be a limitation of EF Core in general. After doing a little bit of research, it appears that the IModel instances are cached as singletons based on the DbContext type. If you place a breakpoint in your OnModelCreating, you'll probably find that it's only being called once per process, despite multiples instantiations.
EF Core assumes a 1:1 relationship between a DbContext and a particular database, and EFCore-MongoDb doesn't behave any differently. I assume that users will create a different DbContext class for each specific named MongoDB database instance with which they want to communicate.
Since you're creating an ETL process, you could also create two derived DbContext types as for example SourceDbContext
and the TargetDbContext
and set the appropriate database names in each context's OnModelCreating method. That would be a cleaner approach from a coding perspective, as it would give a contextual usage to each DbContext.
If you really need to dynamically set the database, you can add a property or extension method on your DbContext:
public string Database
{
get => Model.MongoDb().Database;
set => Model.MongoDb().Database = value;
}
However, this is not a supported use and I'm not sure how it would affect the runtime.
from entityframeworkcore.
To clarify my last comment, the IModel instances aren't cached per process. They're cached per service container. Each time you new up an IServiceCollection and register EF Core or EFCore-MongoDb dependencies, you'll get a fresh instance of the model. However, building the model is a very expensive process that involves heavy use of reflection, so this is not something that should be done dynamically.
So if this is, for example, part of a web application, you should in theory only build the model once per application startup. In that scenario, trying to change the model's database will have serious consequences, and could result in unintended data leaking not only from the source to the target (or vice versa depending on how you're setting the database name) but also between different sets of source and target databases.
If you really, absolutely need to be able to set truly dynamic database names, then your best bet will be to wrap up your ETL related DbContexts into an isolated service container that is instantiated and populated on demand by the parent application. In this scenario, it still would be wisest to have separate Source and Target contexts that are derived from the same abstract base context. This way, you'll ensure that you won't run into any issues with unintended data leaking between the source and target, and especially between different sets of source and target databases.
from entityframeworkcore.
The database attribute convention sets a model annotation. You can find the annotations here, which can be used from OnModelCreating
like this:
public void OnModelCreating(ModelBuilder modelBuilder)
{
var annotations = modelBuilder.MongoDb();
annotations.Database = "DatabaseName";
//apply other settings
}
There's also a convenience method that you can use:
public void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ForMongoDbFromDatabase("DatabaseName");
}
from entityframeworkcore.
As for the connection string: I do not parse it, I just pass it directly to the MongoDB C# driver. A single mongo db connection can open an arbitrary number of databases, so the database name in the connection string is largely ignored. The driver only uses the /database portion as a reference to the database that contains authentication information if the connection string contains credentials. The only time this is different is when the db is "admin", which is used to access db admin commands such as shutting down the database (see the unit tests).
I would prefer not to change the semantics of what a MongoDb connection string means. So for now, please use the attribute or model annotation.
from entityframeworkcore.
Sorry Chris, my mistake about the connection string. About the approach using Annotations on OnModelCreating, I have already tried that, but EF seems to cache the database name among the model info and I was unable to change anymore, once setted. It is there some way to change it at anytime (more than once) like calling GetDatabase() on the c# driver?
from entityframeworkcore.
Two things..,
- I forgot about a third option for setting the database, which is in
MongoDbContextOptionsBuilder
and can be used when setting up the db context:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMongoDb(
"mongodb://localhost",
options => options.UseDatabase("Database"));
}
- Are you also setting the
[Database]
attribute on the db context class? The convention for interpreting this attribute is anIModelBuiltConvention
which is run after the rest of the model has been finalized, after bothOnConfiguring
andOnModelCreating
have been called, which means that the attribute can override anything you're setting in those methods. Please make sure that you're not setting the attribute if you're trying to use direct configuration.
from entityframeworkcore.
I have tried the MongoDbContextOptionsBuilder.UseDatabase approach but seems not to be working at all, the database ended up created with my DbContext class name (ContextMongoDb : DbContext). Subsequent instantiateds DbContexts (on the same process) keeped using this database name.
I am not using the Database attribute.
from entityframeworkcore.
Sorry for the late feedback, worked flawless as you have pointed out.
I have created a new instance of Microsoft.Extensions.DependencyInjection.ServiceCollection on a facade class that receives a delegate (Func<IServiceCollection, IServiceCollection>)
(for multi provider support) where I have pointed to MongoDbEfServiceCollectionExtensions.AddEntityFrameworkMongoDb. I have also overriden the OnConfiguring method like below from a parent abstract DbContext class for automatically set the new serviceProvider (created on my facade class too using the new serviceCollection)
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder
.UseInternalServiceProvider(myCustomServiceProvider);
}
I needed this ability to change the Database at runtime for the same Entity Model due the multi tenancy requirements of my project.
from entityframeworkcore.
Related Issues (20)
- Support for complex property HOT 1
- How can I use dotnet ef dbcontext scaffold HOT 1
- Multiple DbCntexts select query can't work concurrently. HOT 13
- Self refrence read not support HOT 3
- DbSet.Find throws InvalidOperationException HOT 2
- dbContext.DBSet.FirstOrDefault(e => e.FirstName == "xx") missing filter in MongoQueryable HOT 5
- bug: can not modify child HOT 7
- self refrence still can not work HOT 1
- Does this work with IdentityServer4 ? HOT 1
- MissingMethodException in Blueshift.EntityFrameworkCore.MongoDB.Metadata.Conventions.MongoDbRegisterKnownTypesConvention.Apply(InternalEntityTypeBuilder entityTypeBuilder) when using EF Core 2.2 HOT 2
- Wiki Getting Started Installing EFCore-MongoDb error HOT 1
- .NETCore 3 Preview 4 MongoDB.Driver needs upgrade HOT 2
- Still i got this Efcore internal classes problem HOT 1
- Get ObjectDisposedException when execute same query on differend DbContext instances
- Method not found exception
- Entity Framework 3.0 support? HOT 3
- What is the status of tis project? HOT 1
- Hangs on UseMongoDb HOT 2
- Missing Implementation for method HOT 1
- Missing Implementation for method 'get_Info' HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from entityframeworkcore.