I am attempting to use Entity Framework code based migrations with my web site. I currently have a solution with multiple projects in it. There is a Web API project which I want to initialize the database and another project called the DataLayer project. I have enabled migrations in the DataLayer project and created an initial migration that I am hoping will be used to create the database if it does not exist.
Here is the configuration I got when I enabled migrations
public sealed class Configuration : DbMigrationsConfiguration<Harris.ResidentPortal.DataLayer.ResidentPortalContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(Harris.ResidentPortal.DataLayer.ResidentPortalContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
The only change I made to this after it was created was to change it from internal to public so the WebAPI could see it and use it in it's databaseinitializer. Below is the code in the code in the Application_Start that I am using to try to initialize the database
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>());
new ResidentPortalUnitOfWork().Context.Users.ToList();
If I run this whether or not a database exists I get the following error
Directory lookup for the file "C:\Users\Dave\Documents\Visual Studio 2012\Projects\ResidentPortal\Harris.ResidentPortal.WebApi\App_Data\Harris.ResidentPortal.DataLayer.ResidentPortalContext.mdf" failed with the operating system error 2(The system cannot find the file specified.).
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
It seems like it is looking in the totally wrong place for the database. It seems to have something to do with this particular way I am initializing the database because if I change the code to the following.
Database.SetInitializer(new DropCreateDatabaseAlways<ResidentPortalContext>());
new ResidentPortalUnitOfWork().Context.Users.ToList();
The database will get correctly created where it needs to go.
I am at a loss for what is causing it. Could it be that I need to add something else to the configuration class or does it have to do with the fact that all my migration information is in the DataLayer project but I am calling this from the WebAPI project?
I have figured out how to create a dynamic connection string for this process. You need to first add this line into your EntityFramework entry on Web or App.Config instead of the line that gets put there by default.
<defaultConnectionFactory type="<Namespace>.<ConnectionStringFacotry>, <Assembly>"/>
This tells the program you have your own factory that will return a DbConnection. Below is the code I used to make my own factory. Part of this is a hack to get by the fact that a bunch of programmers work on the same set of code but some of us use SQL Express while others use full blown SQL Server. But this will give you an example to go by for what you need.
public sealed class ResidentPortalConnectionStringFactory: IDbConnectionFactory
{
public DbConnection CreateConnection(string nameOrConnectionString)
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["PortalDatabase"].ConnectionString);
//save off the original catalog
string originalCatalog = builder.InitialCatalog;
//we're going to connect to the master db in case the database doesn't exist yet
builder.InitialCatalog = "master";
string masterConnectionString = builder.ToString();
//attempt to connect to the master db on the source specified in the config file
using (SqlConnection conn = new SqlConnection(masterConnectionString))
{
try
{
conn.Open();
}
catch
{
//if we can't connect, then append on \SQLEXPRESS to the data source
builder.DataSource = builder.DataSource + "\\SQLEXPRESS";
}
finally
{
conn.Close();
}
}
//set the connection string back to the original database instead of the master db
builder.InitialCatalog = originalCatalog;
DbConnection temp = SqlClientFactory.Instance.CreateConnection();
temp.ConnectionString = builder.ToString();
return temp;
}
}
Once I did that I coudl run this code in my Global.asax with no issues
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>());
using (ResidentPortalUnitOfWork temp = new ResidentPortalUnitOfWork())
{
temp.Context.Database.Initialize(true);
}
Related
I'm using Xamarin.Forms with EF and SqLite. I've installed the "Microsoft.EntityFrameworkCore.Sqlite" Nuget package in my project. The code issue is in the shared code project, .NetStandard 2.0.
I have created a simple class, let's say CAT class to hold my DB table objects
I can use the "ensurecreated" command and that works fine
I can create a CAT, set properties and SaveChanges() to the DB; this works fine, I can see the data in the DB
I cannot get the data back out; I get an "object not set to a reference..." error.
Ignore my couple of outer curly braces; new to posting code and only way to get it all together in one block. I have handled the platform-specific (Android & iOS) code for obtaining the dbPath to the SqLite .db3 file (not shown here).
Cannot figure what I'm missing that no data will come back out of DB. Any help much appreciated!
{
public class DatabaseContext : DbContext
{
string _dbPath;
public DbSet<Cat> Cats { get; set; }
public DatabaseContext(string dbPath)
{
_dbPath = dbPath;
Database.EnsureCreatedAsync();
}
public async Task<IEnumerable<Cat>> GetCats()
{
var allCats = await Cats.ToListAsync().ConfigureAwait(false);
return allCats;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite($"Filename={_dbPath}");
}
}
List<Cat> itemSource;
// Create Database & Tables
using (var db = new DatabaseContext(App.dbPath))
{
// Ensure database is created
db.Database.EnsureCreated();
// Insert Data
db.Add(new Cat() { IdCat = "111", Fname = "Felix1" });
db.SaveChanges();
// Retreive Data
//method 1
// RESULT: no data are in "itemsource", info reads "exception count = 1"
itemSource = db.Cats.ToList();
// method 2
// RESULTS: crashes with error "System.NullReferenceException: Object reference not set to an instance of an object."
Task<IEnumerable<Cat>> p = db.GetCats();
itemSource = db.Cats.ToList();
}
}
I have an Entity Framework Core database defined in a separate assembly, using the IDesignTimeDbContextFactory<> pattern (i.e., I define a class, derived from IDesignTimeDbContextFactory, which has a method called CreateDbContext that returns an instance of the database context).
Because the application of which the EF Core database is a part utilizes AutoFac dependency injection, the IDesignTimeDbContextFactory<> factory class creates an AutoFac container in its constructor, and then resolves the DbContextOptionsBuilder<>-derived class which is fed into the constructor for the database context (I do this so I can control whether a local or an Azure-based SqlServer database is targeted, based on a config file setting, with passwords stored in an Azure KeyVault):
public class TemporaryDbContextFactory : IDesignTimeDbContextFactory<FitchTrustContext>
{
private readonly FitchTrustDBOptions _dbOptions;
public TemporaryDbContextFactory()
{
// OMG, I would >>never<< have thought to do this to eliminate the default logging by this
// deeply-buried package. Thanx to Bruce Chen via
// https://stackoverflow.com/questions/47982194/suppressing-console-logging-by-azure-keyvault/48016958#48016958
LoggerCallbackHandler.UseDefaultLogging = false;
var builder = new ContainerBuilder();
builder.RegisterModule<SerilogModule>();
builder.RegisterModule<KeyVaultModule>();
builder.RegisterModule<ConfigurationModule>();
builder.RegisterModule<FitchTrustDbModule>();
var container = builder.Build();
_dbOptions = container.Resolve<FitchTrustDBOptions>() ??
throw new NullReferenceException(
$"Could not resolve {typeof(FitchTrustDBOptions).Name}");
}
public FitchTrustContext CreateDbContext( string[] args )
{
return new FitchTrustContext( _dbOptions );
}
}
public class FitchTrustDBOptions : DbContextOptionsBuilder<FitchTrustContext>
{
public FitchTrustDBOptions(IFitchTrustNGConfigurationFactory configFactory, IKeyVaultManager kvMgr)
{
if (configFactory == null)
throw new NullReferenceException(nameof(configFactory));
if (kvMgr == null)
throw new NullReferenceException(nameof(kvMgr));
var scannerConfig = configFactory.GetFromDisk()
?? throw new NullReferenceException(
"Could not retrieve ScannerConfiguration from disk");
var dbConnection = scannerConfig.Database.Connections
.SingleOrDefault(c =>
c.Location.Equals(scannerConfig.Database.Location,
StringComparison.OrdinalIgnoreCase))
?? throw new ArgumentOutOfRangeException(
$"Cannot find database connection information for location '{scannerConfig.Database.Location}'");
var temp = kvMgr.GetSecret($"DatabaseCredentials--{dbConnection.Location}--Password");
var connString = String.IsNullOrEmpty(dbConnection.UserID) || String.IsNullOrEmpty(temp)
? dbConnection.ConnectionString
: $"{dbConnection.ConnectionString}; User ID={dbConnection.UserID}; Password={temp}";
this.UseSqlServer(connString,
optionsBuilder =>
optionsBuilder.MigrationsAssembly(typeof(FitchTrustContext).GetTypeInfo().Assembly.GetName()
.Name));
}
}
Needless to say, while this provides me with a lot of flexibility (I can switch from local to cloud database just by changing a single config parameter, and any required passwords are reasonably securely stored in the cloud), it can trip up the add-migration commandlet if there's a bug in the code (e.g., the wrong name of a configuration file).
To debug those kinds of problems, I've often had to resort to outputting messages to the Visual Studio output window via diagnostic WriteLine calls. That strikes me as pretty primitive (not to mention time-consuming).
Is there a way to attach a debugger to my code that's called by add-migration so I can step thru it, check values, etc? I tried inserting a Launch() debugger line in my code, but it doesn't work. It seems to throw me into add-manager codebase, for which I have no symbols loaded, and breakpoints that I try to set in my code show up as the empty red circle: they'll never be hit.
Thoughts and suggestions would be most welcome!
Add Debugger.Launch() to the beginning of the constructor to launch the just-in-time debugger. This lets you attach VS to the process and debug it like normal.
When setting up our new architecture I followed a guide which used NHibernate with MsSql2008 configuration.
We are not using MsSql2008, instead using Postgresql. The configuration for this all works great and it saves to the database etc.
I am trying to write a unit test to test the UoW but I can't get the InMemory configuration to work.
The guide that I followed used this following Provider:
public class InMemoryNHibernateConfigurationProvider : NHibernateConfigurationProvider
{
public override Configuration GetDatabaseConfiguration()
{
var databaseDriver = SQLiteConfiguration.Standard.InMemory().ShowSql();
return CreateCoreDatabaseConfiguration(databaseDriver);
}
public static void InitialiseDatabase(Configuration configuration, ISession session)
{
new SchemaExport(configuration).Execute(true, true, false, session.Connection, Console.Out);
}
}
My standard (Non UnitTest) configuration looks like this:
public abstract class NHibernateConfigurationProvider : INHibernateConfigurationProvider
{
public abstract Configuration GetDatabaseConfiguration();
public Configuration CreateCoreDatabaseConfiguration(
IPersistenceConfigurer databaseDriver,
Action<Configuration> databaseBuilder = null)
{
var fluentConfiguration =
Fluently.Configure()
.Database(databaseDriver)
.Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Organisation>(new DefaultMappingConfiguration())
//.Conventions.AddFromAssemblyOf<IdGenerationConvention>()
.UseOverridesFromAssemblyOf<OrganisationMappingOverride>()));
if (databaseBuilder != null)
{
fluentConfiguration.ExposeConfiguration(databaseBuilder);
}
return fluentConfiguration.BuildConfiguration();
}
}
public class PostgreSQLServerNHibernateConfigurationProvider : NHibernateConfigurationProvider
{
private static readonly string NpgsqlConnectionString = ConfigurationManager.ConnectionStrings["ProdDBConnection"].ConnectionString;
public override Configuration GetDatabaseConfiguration()
{
return CreateCoreDatabaseConfiguration(
PostgreSQLConfiguration.Standard.ConnectionString(NpgsqlConnectionString).
Dialect("NHibernate.Dialect.PostgreSQL82Dialect").ShowSql(),
BuildDatabase);
}
....... // Other Methods etc
}
How do I write a InMemoryConfigurationProvider that tests using PostgresqlConfiguration instead of SqlLiteCOnfiguration. PostgresqlConfiguration does not have an InMemory option.
Do I implement a configuration that creates another database and just drop it on teardown? Or is there perhaps another way of doing it?
Using sqlite works really well and although it does have some differences to SQL-server which we use they are so minor it doesn't matter for testing purposes.
With that said, this is how we setup the tests:
All test-cases where we want to write/read from db extend the SqLiteTestBaseclass. That way they all get access to a session created by the basesetup method, and can setup the daos / repositories as needed.
Using this approach we also always get a fresh new db for each test-case.
Update:
After trying this out a bit more I actually found that you have to modify it a bit to use InMemory (we had previously used sqlite backed by a file on disk instead). So the updated (complete) setup looks like this:
private Configuration _savedConfig;
[SetUp]
public void BaseSetup()
{
FluentConfiguration configuration =
Fluently.Configure()
.Database(SQLiteConfiguration.Standard
.InMemory)
.ExposeConfiguration(
x => x.SetInterceptor(new MultiTenancyInterceptor(ff)))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>())
.Mappings(m => m.FluentMappings.ExportTo("c:\\temp\\mapping"))
.ExposeConfiguration(x => _savedConfig = x) //save the nhibernate configuration for use when creating the schema, in order to be able to use the same connection
.ExposeConfiguration(x => ConfigureEnvers(x))
.ExposeConfiguration(x => ConfigureListeners(x));
ISessionFactory sessionFactory;
try
{
sessionFactory = configuration.BuildSessionFactory();
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
throw;
}
_session = sessionFactory.OpenSession();
BuildSchema(_savedConfig, _session);
}
private void BuildSchema(Configuration config, ISession session)
{
new SchemaExport(config)
.Execute(false, true, false, session.Connection, null);
}
The reason why you have to jump through all these hoops in order to use the in-memory version of Sqlite is due to the db being tied to the connection. You have to use the same connection that creates the db to populate the schema, thus we have to save the Configuration object so that we can export the schema later when we've created the connection.
See this blogpost for some more details: http://www.tigraine.at/2009/05/29/fluent-nhibernate-gotchas-when-testing-with-an-in-memory-database/
N.B: This only shows the setup of the db. We have some code which also populates the db with standard values (users, customers, masterdata etc) but I've omitted that for brevity.
I made a DLL to include in an ASP (MVC) project, in the DLL there is some 'base' functionality and ofcourse, I'm including it in other MVC projects.
The problem is I have a EF - Code first project now and it's using a Configuration class for the migrations:
internal sealed class Configuration : DbMigrationsConfiguration<Project.Models.DbContextTest>
{
public Configuration()
{
//AutomaticMigrationsEnabled = true;
}
protected override void Seed(Project.Models.DbContextTest context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
When I'm using this configuration i get the following exception:
Sequence contains more than one matching element
On the following function:
return orderBy != null ? orderBy(query).ToList() : query.ToList();
The function is not the problem, because when i remove the configuration class everything is working fine.
The exception is thrown on a query where I get a list of a table, it only has a Primary Key and no related tables (Foreign Keys).
The configuration class is empty, so I'm wondering what it's doing to make my Dll broken?
Thanks in advance,
Stefan
It was a combination of starting the project and doing manual migration.
When starting the project it's auto migrating the code-first models, this in combination with the manual migration gives this errors / exceptions.
We are using EF 6 Code First Migrations in a relatively new project (i.e. there isn't a lot of clutter to contend with). Also, as this is an "enterprise-y" application, we have some specific deployment rules for our target database:
all application level data access must be done through a specific DB user (app-user)
this app-user does not have permissions to create new databases
Therefore, in order to correctly provision a new target database for this application, we need to:
CREATE DATABASE [database_name] CONTAINMENT = PARTIAL
CREATE USER [app-user] WITH PASSWORD=N'p#ssw0rd'
(plus assign specific DB roles to this new user)
I was hoping to carry this out by writing a custom IDatabaseInitializer<TContext>, but it seems that I cannot hook into the database initialization at the correct point.
Conceptually, I want to do this:
have one connection string that is used for read/write access to the DB, using the "controller" app-user user
have a separate connection string that is solely used for provisioning the DB, using more privileged credentials
The code I have tried to use looks a bit like this:
internal class ProvisionThenMigrateInitializer<TContext, TConfiguration>
: MigrateDatabaseToLatestVersion<TContext, TConfiguration>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration _readWriteConfiguration;
private readonly string _provisioningConnectionName;
public ProvisionThenMigrateInitializer(string readWriteConnectionName, string provisioningConnectionName)
{
_provisioningConnectionName = provisioningConnectionName;
_readWriteConfiguration = new TConfiguration
{
TargetDatabase = new DbConnectionInfo(readWriteConnectionName)
};
}
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(false))
{
DbMigrator migrator = new DbMigrator(_readWriteConfiguration);
migrator.Update();
}
}
else
{
// TODO - Create the DB and user here...
string[] sqlStatements =
{
"CREATE DATABASE [database_name] CONTAINMENT = PARTIAL ",
"USE [database_name]",
"CREATE USER [app_user] WITH PASSWORD=N'p#ssw0rd'",
"USE [database_name]",
"ALTER ROLE [db_datareader] ADD MEMBER [app_user]",
"ALTER ROLE [db_datawriter] ADD MEMBER [app_user]",
};
string connectionString = ConfigurationManager.ConnectionStrings[_provisioningConnectionName].ConnectionString;
SqlConnection sqlConnection = new SqlConnection(connectionString);
foreach (SqlCommand command in sqlStatements.Select(sqlStatement => new SqlCommand(sqlStatement, sqlConnection)))
{
command.ExecuteNonQuery();
}
context.Database.Create();
Seed(context);
context.SaveChanges();
}
}
I set the initializer to use in the static constructor of my DbContext derived class:
Database.SetInitializer(new ProvisionThenMigrateInitializer<Context, Configuration>(
DOMAIN_MODEL_CONNECTION_STRING_NAME,
DOMAIN_MODEL_PROVISIONING_CONNECTION_STRING_NAME));
However, when I attempt to use my fancy new custom database initializer, in the following manner, it just plain doesn't work:
using (Context c = new Context())
{
try
{
c.Database.Initialize(true);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
I think that by the time I attempt to call c.Database.Initialize(true) EF has already attempted to connect to the database (using the app_user credentials, not the "provisioning credentials), the connection attempt fails, and we bomb out.
Is it actually possible to use EF 6, Code First and Migrations in a way that will allow this provisioning of my database? If so, what am I doing wrong?
Many thanks.
Here's how I did it:
I have an 'admin' SQL login that is a member of the 'dbcreator' and 'securityadmin' fixed server roles.
I have two connection strings: one specifying the 'admin' sql login, and the other specifying the sql login name I have reserved for use by tenant connections to the db. The 'tenant' login gets created via the initial migration and is granted only reader and writer access to the domain model database.
I have a domain model.
I have my DbContext class.
I have a parameterless constructor on my DbContext class which specifies the ADMIN connection string and is intended to be used to run migrations; and I have another constructor which specifies the TENANT connection string and is the constructor used through the code for all db access made in the context of a logged on tenant user.
public Context()
: base(ADMIN_CONNECTION_STRING_NAME)
{
//etc
and
public Context(int tenantOrgId)
: base(TENANT_CONNECTION_STRING_NAME)
{
Prior to enabling migrations, I used the DbContext in a unit test, which resulted in EF Code First creating the DB catalog.
I have enabled migrations which has produced an inital DbMigration.
I then edited the initial DbMigration "Up" method to provision the tenant sql login and grant it membership to the reader and writer roles:
public override void Up()
{
SqlConnectionStringBuilder domainModelConnectionStringBuilder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings[Context.TENANT_CONNECTION_STRING_NAME].ConnectionString);
string domainModelDatabaseName = domainModelConnectionStringBuilder.InitialCatalog;
Sql(string.Format("IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'gsp_domainmodel_tenant') CREATE LOGIN [gsp_domainmodel_tenant] WITH PASSWORD=N'ge0sp#tia!', DEFAULT_DATABASE=[{0}], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF", domainModelDatabaseName));
Sql(string.Format("USE [{0}]", domainModelDatabaseName));
Sql(string.Format("IF NOT EXISTS (SELECT * FROM [{0}].sys.database_principals WHERE name = 'gsp_domainmodel_tenant') CREATE USER [gsp_domainmodel_tenant] FOR LOGIN [gsp_domainmodel_tenant] WITH DEFAULT_SCHEMA=[gsp]", domainModelDatabaseName));
Sql(string.Format("USE [{0}]", domainModelDatabaseName));
Sql(string.Format("ALTER ROLE [db_datareader] ADD MEMBER [gsp_domainmodel_tenant]", domainModelDatabaseName));
Sql(string.Format("USE [{0}]", domainModelDatabaseName));
Sql(string.Format("ALTER ROLE [db_datawriter] ADD MEMBER [gsp_domainmodel_tenant]", domainModelDatabaseName));
CreateTable( //etc
That is all you need to do if you are happy with the team using Update-Database to apply migrations to their local DBs, and you are happy with exec'ing Migrate.exe on the command line to deploy the db on your build machine, and you are happy with deploying the db changes to production using your own wits.
You can go one step further and specify the MigrateDatabaseToLatestVersion initializer to automate deploying the migrations, both on local dev workstations and on environments that you deploy to.
The trick is that you need to make the MigrateDatabaseToLatestVersion initializer run using the parameterless DbContext constructor so that the migrations are applied in the context of the ADMIN sql login (not the TENANT). That is achieved thusly:
static Context()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion());
// Make the initializer run now, with the parameterless constructor, such that the migrations are run using the admin connection string.
using(var initializerCtx = new Context())
{
initializerCtx.Database.Initialize(true);
}
}
You should be able to do what you want. Key to the matter is making sure context is accessed / renewed with right connection details.
Call the Migrate Method when it suits you in your code.
Change MigrateDatabaseToLatestVersion to match you migration strategy.
EDIT: I will try and summarise the idea and show a snippet sample.
Essentially I use a LUW class that defaults to DONT TOUCH DB.
The Luw needs the DBServer and DBName in constructor
I have a tool that gets the DBConnection for SQL Server
From an Admin ui I have a button. Migrate.
I can then trigger automatic migration when it suits.
I currently use Automatic. But this concept woudl apply fine to managed migrations.
public class Luw{
public Luw(string dataSource, string dbName ){ // constructor
Context = GetContext(dataSource, dbName );
}
public override void MigrateDb() {
// i put this method in my UoW class, I trigger Migrations when I want them to start.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MYDbContext, MYSECIALMigrationConfiguration>());
// Context = GetDefaultContext(); //HERE GET THE CONTEXT WITH CORRECT CONNECTION INFO
Context.Database.Initialize(true);
}
public static MyDbContext GetContext(string dataSource, string dbName)
{
Database.SetInitializer(new ContextInitializerNone<MyDbContext>());
return new MyDbContext((MYTOOLS.GetSQLConn4DBName(dataSource,dbName )),true);
}
public class MYSPECIALMigrationConfiguration : MYBaseMigrationConfiguration<MYDbContext>{ }
public abstract class MYBaseMigrationConfiguration<TContext> : DbMigrationsConfiguration<TContext>
where TContext : DbContext{
protected MYBaseMigrationConfiguration() {
AutomaticMigrationsEnabled = true; // you can still chnage this later if you do so before triggering Update
AutomaticMigrationDataLossAllowed = true; // you can still chnage this later if you do so before triggering Update
}
public clas SQLTOOLS{
// ..... for SQL server....
public DbConnection GetSqlConn4DbName(string dataSource, string dbName) {
var sqlConnStringBuilder = new SqlConnectionStringBuilder();
sqlConnStringBuilder.DataSource = String.IsNullOrEmpty(dataSource) ? DefaultDataSource : dataSource;
sqlConnStringBuilder.IntegratedSecurity = true;
sqlConnStringBuilder.MultipleActiveResultSets = true;
var sqlConnFact = new SqlConnectionFactory(sqlConnStringBuilder.ConnectionString);
var sqlConn = sqlConnFact.CreateConnection(dbName);
return sqlConn;
}