How to use real DB with SQLite in ABP framework? - c#

I'm using Xunit for writing test cases and using ABP framework which is built on top of Asp.Net Core 2.0. I want to connect to my local DB instead of memory DB so that I can verify the records while running test cases.
public static void Register(IIocManager iocManager)
{
RegisterIdentity(iocManager);
var builder = new DbContextOptionsBuilder<MyCompanyDbContext>();
var inMemorySqlite = new SqliteConnection("Data Source=:memory:");
builder.UseSqlite(inMemorySqlite);
inMemorySqlite.Open();
iocManager.IocContainer.Register(
Component
.For<DbContextOptions<MyCompanyDbContext>>()
.Instance(builder.Options)
.LifestyleSingleton()
);
new MyCompanyDbContext(builder.Options).Database.EnsureCreated();
}
So to connect with my local DB I have made the below change, But its giving error. I'm using the same connection string in the application at other places and it works fine.
var inMemorySqlite = new SqliteConnection("Server=.\\SQLEXPRESS; Database=MyLocalDb; Trusted_Connection=True;");

You are trying to use a Non SQLite connection string with a SqliteConnection object.
If the intention is connect to an actual db then the connection string should refer to an actual db file
var optionsBuilder = new DbContextOptionsBuilder<MyCompanyDbContext>();
var connectionString = "Data Source=MyRealLocalDb.db"; //use actual path
optionsBuilder.UseSqlite(connectionString);
//...
Reference Configuring a DbContext

Related

How to `ListCollections` by using only connection string in mongo C# driver?

I'm instantiating MongoClient with full connection string which includes DB :
MongoClient dbClient = new MongoClient("mongodb://***:***#***:27017/myDb");
var dbList = dbClient.ListDatabases();
IMongoDatabase db = dbClient.GetDatabase("myDb");
var collList = db.ListCollections().ToList();
...
This works. But -
If the connection string already includes myDb, then why do I need to write again :
dbClient.GetDatabase("myDb");
?
I've already written myDb in the connection string.
Question:
Is there any option to ListCollections of the DB which already mentioned in the connection string?
One option is to just pull out the database name from the connection string. That might sound a bit messy, but MongoUrl makes it nice and easy. Here's an example:
var connectionString = "...";
var dbName = MongoUrl.Create(connectionString).DatabaseName;
// ...
IMongoDatabase db = dbClient.GetDatabase(dbName);

The underlying provider failed on Open at the time Unity resolve the dependencies

I am using an MVC Application that works with Unity to register all the dependencies of my project. I am also using Entity Framework for the DAL.
In my local machine the application is running fine but at the time I deployed on the server I am receiving an error when Unity is trying to resolve the dependencies.
The underlying provider failed on Open. ... At the time of the exception, the container was: Resolving Class mapped from IClass ... Calling constructor of MyDbContext(System.String connectionName)
1- Does this have a relation with the connection string structure?
Bellow is my connection string
<add name="DBConnection" connectionString="Server=MyServer;Database=MyDatabase;Trusted_Connection=True;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
At this moment I don't have the access to the DB to check if the IIS user has the privileges on the server to run any query, but supposing it doesn't, does this has any relation with the error at the time Unity is trying to resolve the connection string?
2- Does Unity try to open a connection to the DB once it tries to resolve the DBContext?
Here is how I am injecting the parameters
var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString;
container.RegisterType<IUnitOfWork, MyDbContext>(
Activator.CreateInstance<T>(),
new InjectionConstructor(connectionString));
Your problem is most probably tied to fact that your application pool identity on production doesn't have access to the db. Unity creates instance of all dependent classes once the need arises. So if your Class needs IUnitOfWork, unity tries to instantiate MyDbContext.
Let me point out that you shouldn't register instance of entity context (MyDbContext) as singleton in first place - entity framework context is not thread-safe (Entity Framework Thread Safety), also DI is part of critical infrastructure (there shouldn't be IO calls - such as opening the db that can go wrong)
Instead use something like
public interface IEntityContextProvider {
public MyDbContext CreateContext();
}
public class EntityContextProvider : IEntityContextProvider {
public MyDbContext CreateContext() {
return new MyDbContext("ef connection string");
}
}
Usage:
public class SomeClassUsingEF {
// DI
private readonly IEntityContextProvider _entityContextProvider;
// DI
public SomeClassUsingEF(IEntityContextProvider entityContextProvider)
{
if (entityContextProvider == null)
throw new ArgumentNullException(nameof(entityContextProvider));
_entityContextProvider = entityContextProvider;
}
public void SomeQueryToDB() {
using(var context = _entityContextProvider.CreateContext()) {
// select/insert/updates here
}
}
}
Also you connection string looks a lot like "ordinary" connection string - i.e. connection string to db wout entity framework - I'm missing the metadata in it. Code wise its usually something like
private string GetEFConnectionString()
{
string providerName = "System.Data.SqlClient";
string serverName = #".\SQL2008";
string databaseName = "my-db";
// Initialize the connection string builder for the
// underlying provider.
var sqlBuilder = new SqlConnectionStringBuilder();
// Set the properties for the data source.
sqlBuilder.DataSource = serverName;
sqlBuilder.InitialCatalog = databaseName;
sqlBuilder.IntegratedSecurity = true;
// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();
// Initialize the EntityConnectionStringBuilder.
var entityBuilder = new EntityConnectionStringBuilder();
// Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = #"res://*/Model.csdl|
res://*/Model.ssdl|
res://*/Model.msl";
return entityBuilder.ToString();
}

Unable to determine the provider name for connection of type 'Oracle.DataAccess.Client.OracleConnection'

I'm trying to pass existing connection to DbContext, but I get this error:
Unable to determine the provider name for connection of type
Oracle.DataAccess.Client.OracleConnection
What am I doing wrong here?
var oracleConnectionString = ConfigurationManager.ConnectionStrings["OracleConnectionString"].ConnectionString;
var transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
using (var conn = new OracleConnection(oracleConnectionString))
{
conn.Open();
using (var context = new MainDbContext(conn, false))
{
var cmd = #" some sql commandd here ...";
context.Database.ExecuteSqlCommand(cmd);
context.SaveChanges();
}
}
scope.Complete();
}
Connection string:
<add name="OracleConnectionString" connectionString="Data Source=SERVER;Persist Security Info=True;User ID=USER;Password=PASS" />
When you have your edmx file in a different class project, to say your web project, you also need to have the same connection string in the web project.
so...
Class Project:
edmx file
App.Config (connection string for edmx file)
Web Project
Web.Config (same connection string as above.)
Also, take a look here Problems switching .NET project from unmanaged to managed ODP.NET assemblies in case you're missing some Oracle
assemblies.
If using Database First, looks like you can't create new DbContext from Oracle connection string, because EF doesn't know, where to look for metadata. You need to use EF connection, instead of Oracle connection. This is what solved it for me:
var efConnectionString = ConfigurationManager.ConnectionStrings["MainDbContext"].ConnectionString;
using (var conn = new EntityConnection(efConnectionString))
{
conn.Open();
using (var context = new MainDbContext(conn, false))
{
}
}

Change Database during runtime in Entity Framework, without changing the Connection

I have a server that hosts 50 databases with identical schemas, and I want to start using Entity Framework in our next version.
I don't need a new connection for each of those databases. The privileges of the one connection can talk to all of the 50 databases, and for data management and speed (this is a WebAPI application) I don't want to instantiate a new EF context every time I talk to each of the databases if I don't have to, unless of course if this occurs each time a request comes to the server then no big deal.
All I really need is the ability to change the USE [databasename] command, which I assume eventually gets sent to the server from EF.
Is there a way to accomplish this in code? Does EF maintain a read/write property in the Context that refers to the database name that could be changed on the fly before calling SaveChanges(), etc.??
Thank you!!!
bob
Don't Work hard, work smart !!!!
MYContext localhostContext = new MYContext();
MYContext LiveContext = new MYContext();
//If your databases in different servers
LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("localhost", "Live");
//If your databases have different Names
LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("DBName-Localhost", "DBName-Live");
the structure for databases should be the same ;)
You can take a look at:
SO question about passing existing SQL Connection to
EntityFramework Context
and at this article describing how to
change database on existing connection.
Please let me know if any additional help is needed.
Edited
Updated 2nd link to point to SqlConnection.ChangeDatabase method.
So eventually code would look similarly to the following:
MetadataWorkspace workspace = new MetadataWorkspace(
new string[] { "res://*/" },
new Assembly[] { Assembly.GetExecutingAssembly() });
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
using (EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection))
using (NorthwindEntities context = new NorthwindEntities(entityConnection))
{
// do whatever on default database
foreach (var product in context.Products)
{
Console.WriteLine(product.ProductName);
}
// switch database
sqlConnection.ChangeDatabase("Northwind");
Console.WriteLine("Database: {0}", connection.Database);
}
It is very simple
I had
public WMSEntities() : base("name=WMSEntities") //WMSEntities is conection string name in web.config also the name of EntityFramework
{
}
already in autogenerated Model.Context.cs of edmx folder.
To connect to multiple database in runtime, I created another constructor that takes connection string as parameter like below in same file Model.Context.cs
public WMSEntities(string connStringName)
: base("name=" + connStringName)
{
}
Now, I added other connection string in Web.Config for example
<add name="WMSEntities31" connectionString="data source=TESTDBSERVER_NAME;initial catalog=TESTDB;userid=TestUser;password=TestUserPW/>
<add name="WMSEntities" connectionString="data source=TESTDBSERVER_NAME12;initial catalog=TESTDB12;userid=TestUser12;password=TestUserPW12/>
Then, when connecting to database I call below method passing connectionString name as parameter
public static List<v_POVendor> GetPOVendorList(string connectionStringName)
{
using (WMSEntities db = new WMSEntities(connectionStringName))
{
vendorList = db.v_POVendor.ToList();
}
}
Here's my solution for just changing the database name. Simply pull the string from the web or app.config file, modify it, and then instantiate:
string yourConnection = ConfigurationManager.ConnectionStrings["MyEntities"].ConnectionString.Replace("MyDatabase", yourDatabaseName);
dcon = new MyEntities(yourConnection);
I have implemented this in my current project in which we have a common security database and different database for every client in the project. So our security database has a table that contain connection string for every other database. We just pass client id and get the connection string of the client database..
For this add two EDMX one for the common database and other for common schema databases. When user login or what might be your scenario to choose database go to common databse and get the connection string and create object of the needed database. Here is Code sample any, if any quer let me know..
You can keep connection string regarding every other database in a table in a a common database shared by all the other database.
EntityInstance_ReviewEntities.GetContext(GetConnectionString(ClientId));
private string GetConnectionString(int TenantId)
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
ISecurityRepository objSecurity = new SecurityRepository();
string tenantConnectionString = objSecurity.GetClientConnectionString(TenantId);
entityBuilder.ProviderConnectionString = tenantConnectionString;
entityBuilder.Provider = "System.Data.SqlClient";
entityBuilder.Metadata = #"res://*/ClientEntity.YourEntity.csdl|res://*/ClientEntity.ADBClientEntity.ssdl|res://*/ClientEntity.YourEntity.msl";
return entityBuilder.ToString();
}
EntityConnection.ChangeDatabase method is not supported, but SqlConnection.ChangeDatabase works fine.
So you have to use SqlConnection in entity framework database's constructor:
using MvcMyDefaultDatabase.Models;
using System.Data.Metadata.Edm;
using System.Data.SqlClient;
using System.Data.EntityClient;
using System.Configuration;
using System.Reflection;
public ActionResult List(string Schema)
{
SqlConnection sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
MetadataWorkspace workspace = new MetadataWorkspace(new string[] { "res://*/" }, new Assembly[] { Assembly.GetExecutingAssembly() });
EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection);
sqlConnection.Open();
sqlConnection.ChangeDatabase(Schema);
Models.MyEntities db = new MyEntities(entityConnection);
List<MyTableRecords> MyTableRecordsList = db.MyTableRecords.ToList();
return View(MyTableRecordsList);
}
With this code you can read the tables with the same format (same table name and same fields) of several schema passing the database name in the "Schema" string.
For SQL Server, if you want to change only the database, not a connection, try:
public class XXXXDbContext : DbContext
{
public string databaseName
{
set
{
Database.GetDbConnection().Open();
Database.GetDbConnection().ChangeDatabase(value);
}
}
}

How do you use the mvc-mini-profiler with Entity Framework 4.1

I am trying to use the mvc-mini-profiler with MVC3 and keep getting the following error
Unable to determine the provider name for connection of type 'MvcMiniProfiler.Data.ProfiledDbConnection'
Below is the code that I am using to try and instatiate my Context.
DbConnection conn = new MySqlConnection(
ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString);
var profiledConnection = MvcMiniProfiler.Data.ProfiledDbConnection.Get(conn);
return new DB(profiledConnection);
And here is the DB Context Class.
public class DB:DbContext, Stats.Data.IDB
{
public DB(DbConnection conn)
: base(conn, true)
{
}...
As of version 1.5 this is now supported see: http://code.google.com/p/mvc-mini-profiler
The step to configure it are listed here: Using mvc-mini-profiler database profiling with Entity Framework Code First

Categories