MigratorDotNet for Plugins Architecture - fluent-migrator

We're starting to use Migrator.NET for managing our database migrations, its fantastic but we have an additional requirement that plug-ins written for our software which require their own custom fields added (depending on the plug in of course).
So basically we have a our core database tables, and our plugin specific tables.
I was hoping that in Migrator.NET I would see some sort of additional attribute like this
[Migration(1, "Core")
public class Migration1 : Migration
{
}
so that I'd be able to then plug in developers would then be able to do something like
[Migration(1, "PluginName")
public class Migration1 : Migration
{
}
Unfortunately this parameter doesn't exist, and the version table doesn't seem to have any place to store a tag/plugin name
CREATE TABLE [dbo].[VersionInfo](
[Version] [bigint] NOT NULL,
[AppliedOn] [datetime] NULL
) ON [PRIMARY]
Does anybody have any ideas how I would go about doing this?
I've seen that Ruby/Redmine support this sort of architecture as they allow plugins to include their own db migrations, however would love to be able to do this in MigratorDotNet.

You mentioned you're tagging, and you can filter migrations based on Tags, like so:
[Tags("DK", "NL", "UK")]
[Tags("Staging", "Production")]
[Migration(1)]
public class DoSomeStuffToEuropeanStagingAndProdDbs() { }
See the following wiki page for more details:
https://github.com/schambers/fluentmigrator/wiki/Filter-migrations-run-based-on-Tags

Related

How to write Fluent NHibernate convention for constraint names?

I am using Fluent NHibernate 3.1.0 (with NHibernate 5.3.8) for my domain mappings. The project I am working on is targeting .NET 5. The database engine used is SQLite with the data provider System.Data.SQLite 1.0.113.7.
I am trying to find a way to apply convention for constraint names in my project. I really want to avoid names like FK_935624DA.
I cannot find the answer anywhere, but I am certain the infos is somewhere but I am overlooking! Of course I read the following (official) documentation on GitHub.
https://github.com/nhibernate/fluent-nhibernate/wiki/Conventions
I have to say that however, by example I managed to define a custom foreign key convention that way:
internal class ForeignKeyNameConvention : ForeignKeyConvention
{
protected override string GetKeyName(Member property, Type type) => type.Name + "ID";
}
Can you point me out in the right direction with a code sample or a link?
Thanks !
P.S. If I missed some infos, let me know, I am not really used to post on Stack Overflow.

Working with 2 databases and just one entity manager in Symfony2

I need to keep an archive database to an application in Symfony2.
In it I'll keep all records older than 90 days. I was thinking that I could use just one entity manager (because both databases are identical).
First of all, I'm not sure if this is the best approach/solution.
And, besides that, I don't know how to implement this idea (I've just found 2 entity managers for 2 databases).
I'm sorry if this is a dumb question, but I've been looking for some solution for it for 2 days now.
We use distinct em for saving history, works fine.
Code looks like this.
Somewhere in your config...
yourpath\app\config\parameters.yml
parameters:
database_driver: pdo_mysql
database_host: site1.ru
database_port: 3346
database_name: db1
database_user: roof
database_password: jump
database_history_driver: pdo_mysql
database_history_host: site2.ru
database_history_port: 10001
database_history_name: history
database_history_user: sea
database_history_password: deep
etc...
Somewhere in your history bundle...
/**
* We make history!
**/
class historyController extends Controller
{
public function showAction($historyId)
{
// get secondary manager
$emHistory = $this->getDoctrine()->getManager('history');
// get default manager
$em = $this->getDoctrine()->getManager('default');
}
}
Somewhere in services of history bundle
class HistoryBundleUtils {
protected $em;
public function __construct($arguments) {
// get secondary manager
$this->em = $arguments['entityManager']->getManager('history');
# etc...
}
}
This isn't possible, each Entity Manager can only use one DB connection, the docs seem quite clear about it.
So I think you'll be stuck with using two EMs. Each will be configured with a duplicate set of your mappings. The detail of how you use them is up to you though:
You could just manually choose one or the other as required in your app
You could somehow abstract it away into a class of your own which has both EMs, and then when you run queries etc it will be worrying about where to get the data from (and possibly how to combine data from both EMs)
If the only activity which really needs both EMs is the archive process itself, that's an obvious thing to hide away in a class nicely
I suppose it also depends on what the point of the archive DB is. If it's some architectural thing like it needs to be on a different server or whatever, then you're stuck as above. On the other hand, if you really just want old data not to show up in day-to-day queries (without specifically asking for it), then it might be better to implement some kind of "archived" flag and a Doctrine Extension which magically hides archived items away until you ask for them, very similar to SoftDeleteable
I don't know if it is a good practice but I have been using one EM for two Databases successfully in Symfony2. The project I was working on required access to two databases. There are some limitations however. First the database_user and _password needs to be the same for both databases. You can access both databases, but you can only create (with console doctrine:database:create) and write the tables (console doctrine:schema:update) of the one defined in parameters.yml.
You can read, write, update, delete on both databases, but you need to specify the database name of your second database in the model, like:
#ORM\Table(name="my_other_database.my_table")
Basically, you can use one EM for two Databases, if one database already exists and you only need to access it.

Custom fields in ASP.Net Login/Register?

I have to edit the Login/Registration that ASP provides to include a custom dropdown ("BranchID") menu that saves to the database so each user has its own Branch. I am using ASP Membership system, and of course it saves to the ASPNETMDF database it creates. Googling has net me some results but I am quite confused. I know there are "User Profiles", and I I can save this Profile data, but what I am not quite sure is if its a temporary measure or if it does record to the database.
I could make my own custom membership system, use the built it and adapt it or use the user profiles. What is the best course of action? I'd vastly prefer to adapt/edit the built in Membership system and add the data I require to it but I still don't haven't a clear answer to what I should do or what's best.
You have two choices:
Create a CustomMembershipProvider , and if you need to a CustomRoleProvider, you can do this by implementing .NET's MembershipProvider. Sample: http://www.codeproject.com/Articles/165159/Custom-Membership-Providers
Create a separate table that stores additional user information, i.e., "BranchID", and add a one-to-one relationship between your table and .NET's Membership
It's really up to you which one you choose.
MembershipProvider is pretty easy to extend. Assuming the branch is something they have to select to authenticate? You should be able to extend authenticate to do something like:
public class MyCustomMembershipProvider : MembershipProvider
{
/*
....
*/
public bool ValidateUser(string username, string password, string branch)
{
return (::ValidateUser(username, password) && MyCustomRoutine(username, branch));
}
}

ASP.NET MVC4 - Error When Customize Default Accounts Models & Controller

I am in the begining of making a simple website using ASP.NET MVC4 CodeFirst Approach. The web site is built around users who are able to register, make posts etc. The existing UserProfile class was modified for the accommodation other fields (ex: FirstName, LastName etc).
When I ran the website I got a similar error:
Invalid column name 'FirstName'.
Invalid column name 'LastName'.
Invalid column name 'Phone'.
I red that this is because the Database is not updated as the model is updated. So I set the following on the Application_Start() in Global.asax with the intention of droppnng the database always (at least until I get the hang of it).
protected void Application_Start()
{
Database.SetInitializer(new DropCreateDatabaseAlways<UsersContext>());
//Other default generated stuff below...
}
I also tryed the DropCreateDatabaseIfModelChanges, but both methods didn't drop the database.
Isn't this possible? Why is it? Am I doing some thing wrong?
I believe it would be possible to store the info in a different table and link it to this, but I prefer to keep it in one table.
Also is it a bad idea to add UserProfiles to the websites context (lets say: DatabaseContext (which has other entities like Posts, Comments etc) and change the AccountsController to use DatabaseContext instead of UsersContext?
Thanks in advance.
Have you run Enable-Migrations in the Package Manager Console? You should see a migration folder in your project, with a configuration.cs file, ensure you have enabled automatic migrations.
public Configuration(){
AutomaticMigrationsEnabled = true;
//if you drop columns - consider this carefully...
AutomaticMigrationDataLossAllowed = true;
}

Entity Framework for Multi-tenant architecture - filterings single table by tenant ID

We are looking for a way of automatically filtering all CRUD operations by a tenant ID in Entity Framework.
The ideas we thought of were:
Using table valued user defined functions
Using stored procedures (but we don't really want to, as we're using an ORM to avoid doing so)
Some how modifying the templates used to generate the SQL to add a where clause on each statement.
Some how modifying the templates used to generate the LINQ in the controllers (we may use MVC).
Any tips?
-thanks
Alex.
Using table valued user defined functions
Table valued function are only available in .NET 4.5 Beta (and not available in code first). Using them will still not help you because you will have to use the function in every LINQ query so it is the same as using where clause.
Using stored procedures (but we don't really want to, as we're using an ORM to avoid doing so)
It can be useful for some special complex queries but generally it is not what you want.
Some how modifying the templates used to generate the SQL to add a where clause on each statement.
Too complex and on completely different level of abstraction.
Some how modifying the templates used to generate the LINQ in the controllers (we may use MVC).
Close to ideal solution. You simply need to wrap access to your entity set into some code which will look like:
public class MultiTenantAccess<T> where T : IMultitenant
{
private IDbSet<T> set;
...
public IQueryable<T> GetQuery(int tenantID)
{
return set.Where(e => e.TenantID == tenantID);
}
}
Sometimes this is core for something called Generic repository but it is really just a wrapper around EF set. You will always use GetQuery to query your data store instead of using DbSet directly.
you may also separate the tenants data into different databases
or into same database, but with different schemas? You can read more about this in an old MSDN article called "Multi-Tenant Data Architecture"

Resources