Get database name within Up method of Migration - fluent-migrator

How do I get the name of the database that a migration is operating over from within the Up (or Down) method of a class that extends Migration
public class BaseMigration : Migration
{
public override void Up()
{
var databaseName = HOW_DO_I_GET_THIS?
}
}

You can derive the database name from the connection string if you have it specified there. For example, this will work if you're using SQL server:
public class BaseMigration : Migration
{
public override void Up()
{
System.Data.SqlClient.SqlConnectionStringBuilder builder =
new System.Data.SqlClient.SqlConnectionStringBuilder(ConnectionString);
var databaseName = builder.InitialCatalog;
}
}
Otherwise, use one of the other available
System.Data.Common.DbConnectionStringBuilder implementations:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
See this stackoverflow post for more information.

Related

No changes in model, should EF migration create empty empty Up() Down() methods? Or no migration at all?

I'm using EntityFrameworkCore Code First to create my SQL migration scripts.
After every change in my model, I run Add-Migration changeInModel and a corresponding XXXXXXXX_changeInModel.cs file is being generated in my Migrations folder.
If I don't make any change in my models AND I run Add-Migration noChangeInModel , I was assuming (out of nowhere) no generation of XXXXXX_noChangeInModel.cs
However, EF Core is creating a XXXXXX_noChangeInModel.cs with an empty Up and Down methods.
Is that supposed to be the expected behavior? Or should EF Core just skip the generation of an empty .cs file? I can't find any reference to this in the documentation.
I have taken my main project and stripped out all the code up to the bare minimum to find out whether is the behavior or some sort of bug in my configuration.
Below the minimum core to reproduce generating empty Up/Down methods with no change in models, with the following Nuget packages:
Microsoft.EntityFrameworkCore 2.2.6
Microsoft.EntityFrameworkCore.SqlServer 2.2.6
Microsoft.EntityFrameworkCore.Tools 2.2.6
Microsoft.NETCore.App 2.2.0
namespace TestingEFCore
{
public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<BloggingContext>
{
public BloggingContext CreateDbContext(string[] args)
{
var connectionString = "Server=localhost;Database=TEST2;Integrated Security=SSPI;";
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlServer(connectionString);
return new BloggingContext(optionsBuilder.Options);
}
}
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
}
I would expect no XXXXXX_noChangeInModel.cs being generated, but a I get migrations with empty Up/Down methods. I can't find the documentation to describe this use case.
I think it is expected behavior. Consider the case when you have no changes in model but you need to add some data in your db like this
public partial class your_migration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(#"your sql");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(#"sql to clean up data");
}
}
Without an empty migration for no changes in model generated it would be impossible to obtain such migration.

Create Singleton instance in MEF2

I'm creating an application with multiple plugins using MEF2 (Microsoft.Composition). These plugins should import some common object and they should all share the same instance of this object... so a typical Singleton.
However, when I [Import] this common object into my plugins they all get their own copy instead of a shared one.
In .NET Framework MEF1, all object were created as singletons by default. This does not seem to be the case for .NET Core MEF2.
How can I make sure that all my plugins get the same singleton instance of my common object?
Sample code
Startup
static void Main(string[] args) {
ContainerConfiguration containerConfig = new ContainerConfiguration()
.WithAssembly(Assembly.GetExecutingAssembly())
.WithAssembly(typeof(ICommonObject).Assembly);
using (CompositionHost container = containerConfig.CreateContainer()) {
_mainApp = container.GetExport<MainApp>();
_mainApp.Start();
}
}
MainApp
[Export(typeof(MainApp))]
public class MainApp {
[Import] public ICommonObject CommonObject { get; set; }
[ImportMany] public IEnumerable<IPlugin> Plugins { get; set; }
public void Start() {
CommonObject.SomeValue = "foo";
Console.WriteLine("SomeValue (from MainApp): " + CommonObject.SomeValue);
foreach (IPlugin plugin in Plugins) {
plugin.Start();
}
}
}
Plugin
[Export(typeof(IPlugin))]
public class SomePlugin : IPlugin {
[Import] public ICommonObject CommonObject { get; set; }
public void Start() {
Console.WriteLine("SomeValue (from plugin): " + CommonObject.SomeValue);
}
}
Output
SomeValue (from MainApp): foo
SomeValue (from plugin):
After much trial and error I seem to have finally found a solution myself.
The trick seems to be to use ConventionBuilder. This has an extension method called .Shared() which makes all objects derived from a specific type into a Singleton.
For my code examples, just add the following to the top of the Startup code:
ConventionBuilder conventions = new ConventionBuilder();
conventions.ForTypesDerivedFrom<ICommonObject>()
.Export<ICommonObject>()
.Shared();
ContainerConfiguration containerConfig = new ContainerConfiguration()
.WithAssembly(Assembly.GetExecutingAssembly(), conventions);
For some reason, the object implementing ICommonObject doesn't even need an [Export] attribute. In any case, the output from the example is now:
SomeValue (from MainApp): foo
SomeValue (from plugin): foo

SqliteConnection Xamarin forms Exception Unhandled?

When i try to run the project, i am getting this kind of error: "System.NullReferenceException: Object reference not set to an instance of an object"
pointing in this code:
sqliteconnection = DependencyService.Get().GetConnection();
This is my Class for DB actions:
namespace DevoApp.DevoAppFinal.Helpers
{
public class DatabaseHelper
{
static SQLiteConnection sqliteconnection;
public const string DbFileName = "Devotion.db";
public DatabaseHelper()
{
sqliteconnection = DependencyService.Get<ISQLite>().GetConnection();
sqliteconnection.CreateTable<Devotion>();
}
// Get All Contact data
public List<Devotion> GetAllDevotionsData()
{
return (from data in sqliteconnection.Table<Devotion>() select data).ToList();
}
//Get Specific Contact data
public Devotion GetDevotionData(int id)
{
return sqliteconnection.Table<Devotion>().FirstOrDefault(t => t.devotionalId == id);
}
// Delete all Contacts Data
public void DeleteAllDevotions()
{
sqliteconnection.DeleteAll<Devotion>();
}
// Delete Specific Contact
public void DeleteDevotion(int id)
{
sqliteconnection.Delete<Devotion>(id);
}
// Insert new Contact to DB
public void InsertDevotion(Devotion contact)
{
sqliteconnection.Insert(contact);
}
// Update Contact Data
public void UpdateDevotion(Devotion contact)
{
sqliteconnection.Update(contact);
}
}
}
When using the DependencyService, you have to implement the interface in each targeted platform project.
In this case, you should have the ISQLite interface implemented on the platforms you're targeting, i.e. iOS and Android.
To make Xamarin find it at runtime, you will have to register the implementation with the Dependency attribute above the namespace. Observe the following example based on a few assumptions of your project.
In your shared library you have declared the interface:
public interface ISQLite
{
// Members here
}
Nothing fancy going on there. Then for each platform, you want to run the app on, do something like this:
[assembly: Xamarin.Forms.Dependency (typeof (SQLiteImplementation_iOS))]
namespace DevoApp.DevoAppFinal.iOS
{
public class SQLiteImplementation_iOS : ISQLite
{
// ... Your code
}
}
From the error, it looks like you forgot to add the attribute

ASP.NET 5 - Using a Configuration Setting

I am playing with ASP.NET 5. I am trying to understand the new configuration model. I have read several articles. However, I am still unsuccessful in loading a configuration setting. My config.json file looks like this:
{
"App" : {
"Info" : {
"Version":"1.0.0",
"ReleaseDate":"03-15-2015"
}
}
}
My Startup.cs file looks like this:
public class Startup
{
public IConfiguration Configuration { get; private set; }
public Startup()
{
Configuration = new Configuration()
.AddJsonFile("config.json");
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseErrorPage();
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index" });
});
app.UseMvc();
app.UseWelcomePage();
}
}
In one of my controllers, I have the following
MyController.cs
using System;
using Microsoft.AspNet.Mvc;
namespace MyOrg.MyApp
{
public class MyController : Controller
{
[HttpGet()]
public ActionResult Index()
{
var version = Configuration.Get("App:Info:Version");
return new HttpStatusCodeResult(200);
}
}
}
When I start the app, I get an error that says:
error CS0103: The name 'Configuration' does not exist in the current context
at Microsoft.Framework.Runtime.Roslyn.RoslynProjectReference.Load(IAssemblyLo
adContext loadContext)
at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name,
IAssemblyLoadContext loadContext)
at Microsoft.Framework.Runtime.Loader.ProjectAssemblyLoader.Load(String name)
at kre.host.LoaderContainer.Load(String name)
at kre.hosting.RuntimeBootstrapper.<>c__DisplayClass6_0.<ExecuteAsync>b__4(As
semblyName assemblyName)
at kre.hosting.RuntimeBootstrapper.<>c__DisplayClass6_0.<ExecuteAsync>b__7(Ob
ject sender, ResolveEventArgs a)
at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
What am I doing wrong? I feel like I've followed the examples I've seen. Yet, I can figure out what I'm doing wrong.
Clearly you want to access Configuration property in your Startup class. And the error method says it doesn't know what Configuration is. So you need a using statement or a fully qualified name. Also, you should avoid naming things the same thing as stuff found in the framework. Your Startup class has a Configuration property, but it also tries to use the Configuration class from Microsoft.Framework.ConfigurationModel. How confusing is that?
Your Configure() method in Startup needs a using statement or fully qualified name so it knows what the Configuration class is.
using Microsoft.Framework.ConfigurationModel; //at the top of your class
Configuration = new Configuration(); //later in the code, we can access without fully qualifying name
or
Configuration = new Microsoft.Framework.ConfigurationModel.Configuration();
In your controller, you may have a similar issue. Replace MyOrg.MyApp.Startup in the example below with whatever the namespace is for your Startup class.
using MyOrg.MyApp.Startup //at the top of your class
Startup.Configuration.Get("App:Info:Version"); //later in the code, we can access without fully qualifying name
or
MyOrg.MyApp.Startup.Startup.Configuration.Get("App:Info:Version");
Better way of doing things
That should be enough to get you started. However, accessing the Startup class to retrieve your configuration isn't ideal, because now your controller's action methods depend on having the Startup class there. That's not very unit testable. Ideally your controllers should be isolated from each other. You should define some sort of interface to hold the configuration info you want, then have the controller depend on that interface. When you're in your site, you'll respond with a class specific to the site's configuration. When unit testing, you can have tight control over the test values by using a different class.
interface ISiteConfig
{
string Version {get; set;}
DateTime ReleaseDate {get; set;}
}
public class SiteConfig : ISiteConfig
{
public string Version {get; set;}
public DateTime ReleaseDate {get; set;}
public SiteConfig()
{
var c = new Configuration()
.AddJsonFile("config.json");
Version = c.Get("App:Info:Version");
ReleaseDate = c.Get("App:Info:ReleaseDate"); //may need to parse here
}
}
public class TestConfig : ISiteConfig
{
public string Version {get; set;}
public DateTime ReleaseDate {get; set;}
public TestConfig(string version, DateTime releaseDate)
{
Version = version;
ReleaseDate = releaseDate;
}
}
Then you'd use Dependency Injection to inject instances of your configuration into the Controller.
public class MyController : Controller
{
private readonly ISiteConfig Config;
public MyController(ISiteConfig config)
{
Config = config;
}
[HttpGet()]
public HttpStatusCodeResult Index()
{
var version = Config.Version;
return new HttpStatusCodeResult(200);
}
}
public class Startup
{
public void Configure(IBuilder app)
{
...
app.UseServices(services =>
{
...
// Set up the dependencies
services.AddTransient<ISiteConfig, SiteConfig>();
...
});
...
}
}
Now you can more easily unit test your action methods, because your unit tests can use the TestConfig class while the site can use the SiteConfig class. And also if you want to change how your configuration is done, you don't have to replace strings in a bunch of different places. You'll have one class where you do so, the rest is strongly typed and easy to change without blowing up your application.
Your unit test might look like this:
//Arrange
var testConfig = new TestConfig("1.0", DateTime.Now );
var controller = new MyController(testConfig );
//Act
var response = controller.Index();
//Assert
Assert.AreEqual(200, response.StatusCode);
As of Beta 5 the accepted answer is no longer correct. There is no longer a Get method on IConfiguration. Also the way of constructing the configuration object is also changed.
The following code works on Beta 7:
// showing using statements here since this is new from Beta 5
using Microsoft.Dnx.Runtime; // renamed was Microsoft.Framework.Runtime
using Microsoft.Framework.Configuration; // renamed was Microsoft.Framework.ConfigurationModel
// other using statements here
// Startup constructor. Note: now takes IApplicationEnvironment
// this is required in order to get base path
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
// Setup configuration sources.
var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
.AddJsonFile("config.json")
.AddJsonFile("dbconfig.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
// property to hold configuration object created in constructor
public IConfiguration Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
// this will bind to an IOptions<AppSettings> instance
// where AppSettings is a class you define that has a set of
// properties that match your configuration section loaded from the
// json file
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
// here I am loading a connection string from a json file and passing into an
// new EF 6.x DB Context class
services.AddInstance<TalentAgencyContainer>(new TalentAgencyContainer(Configuration["ConnectionStrings:TalentAgencyContainer"]));
// Add MVC services to the services container.
services.AddMvc();
}

Testable design

I have a java class which has a static member created using Facade (Singleton).
Class A implements InterfaceA {
private static DataStore db = DataStoreFacade.getInstance("BDB"); //singleton instance
public void save(final String key, final String val) {
db.save(key,val);
}
};
Here Class A is used as a member variable for webservice (stateless bean).
I can't test this code using EasyMock because there is no way to override the DataStore instance.
There are two options.
Have a constructor taking the instance of DataStore which will set to db member variable. The problem is I don't want webservice class to know which datastore instance has been created.
Provide an additional protected Set Method to override the db object. This is what I have used where I create a Easy Mock object of DataStore and override the member variable. Is it the correct design.
What are the other possibilities?
You're right that is bad for testability. Use dependency injection and don't go for static variable:
public class A implements InterfaceA {
private DataStore db;
public A(DataStore db) {
this.db = db;
}
...
}
to inject or build either use dependency-injection framework (e.g. spring) or build the object somewhere in bootstrap factory code yourself.
production code:
new A(DataStoreFacade.getInstance("...");
test-code:
public void test_xxx(){
DataStore db = EasyMock.createMock(DataStore.class);
//... do some expectations and replay(db)
InterfaceA a=new A(db);
//...
}
Well, the original code is already testable. Here is a unit test for it, using JMockit:
#Test
public void testSave(final DataStore mockDb)
{
final String key = "aKey";
final String value = "aValue";
new A().save(aKey, aValue);
new Verifications()
{{
mockDb.save(key, value);
}};
}
If needed, the DataStoreFacade class could be mocked too.
Why not make the db member protected, and in your test project inherit it and override that member:
project
{
Class A
{
protected static db = ...
public void Save(...) { ... }
}
}
test_project
{
Class B : A
{
protected override static db = ... (create test db)
}
Class testB
{
public A a;
public void Setup()
{
this.a = new B();
}
public void TearDown()
{
// delete a
}
public void TestSaveKey()
{
// test a
}
}
}
It's still hidden from consumers of the code/library, the test object isn't cluttering the production code, and the behaviour will be tested as if it were the production version.
Beware though, that having a static member for your db object could cause troubles for your tests if it's not cleaned up properly after each test.*
I know that you probably already know this, but I'm saying it for completeness.
Use the Supersede Instance pattern...
http://goodcoffeegoodcode.blogspot.com/2010/01/supercede-instance-pattern.html

Resources