I am building a composite (Prism) WPF application. I hava managed to build some core elemets: for example module discovery from folder.
I am also using NHibernate (Fluent) to persist data. I was able to separate modules so every has it's own model and mapping, and when Prism adds module it also adds mappings to my nh configuration.
What I would like to do is to insert some startup records when a module, that has never been started, is enabled.
For example:
When I first start my app, it detects that there is no db and creates one, only with one configuration table. This table contains info about which module is enabled. Then admin can configure app through UI which modules should be enabled. Next time the app starts it detects new tabs from newly enabled modules and creates their tables using NH UpdateSchema. What I would like to do is to also insert some startup records with this table create.
I think this should be done by NH events (NH documentation on events). Something like 'PostTableCreateEvent' would be nice but I can't find anything like this.
Did any of you do something like this?
Events are triggered in sessions but Schemaexport doest take sessionfactories or sessions, so you cant hook in there. For this what you want there is <database-object><create>INSERT ...</create><drop></drop></database-object> in xml mappings or plain sql since FNH doesnt support <database-object> afaik.
Option 1: add fluent and hbm.xml mappings on creation of NH-Configuration and embed Mappings with <database-object>
Option 2: allow Modules to take additional steps (sql) after Creation of tables ( for one of my projects i wrapped Schemaexport in my own class/Method which also creates the database itself which isnt handled by schemaexport and inserts custom data like schemaversion and configs)
Related
I'm trying to understand the different types of migration paths we can choose when developing an ASP.NET Core 1.0 application with EF Core. When I created my first Core application I noticed it generated a ApplicationDbContextModelSnapshot class that uses a ModelBuilder to build the model.
Then I read that if I need to add a table to the database, I need to create the new model and run the command line to generate the migration file and update the database. Ok, I get it up to this point.
But when I do that, I notice that the ApplicationDbContextModelSnapshot class gets updated too.
1) Does that mean I cannot modify this ApplicationDbContextModelSnapshot class since it looks like it gets regenerated each time?
2) Should I use Data Annotations to build my model or should I use Fluent API which tells me to build my model in the ApplicationDbContext class? Huh? another file that builds the model?
I'm seeing three different ways of working with the database here, the snapshot class, data annotations, and fluent API. I'm confused because today, I made a mistake in my last migration file so I deleted the file, dropped the database and reran the database update.
But by doing that I got errors similar to:
The index 'IX_Transaction_GiftCardId' is dependent on column 'GiftCardId'.
ALTER TABLE ALTER COLUMN GiftCardId failed because one or more objects access this column.
So naturally I was wondering if I had to modify the ApplicationDbContextModelSnapshot class.
What is the path I should be taking when it comes to migrations or database updates because these three paths are confusing me.
I have run into this issue before when I create migrations, make model changes, create new migrations, and try to update the database. The root cause is when keys are being changed and relationships are not dropped and are not added back or do not exist.
You have two options
Easy Method
The easiest way is also the most destructive way and only possible in a dev environment.
Delete all migrations, drop the database, create new migrations and run 'update-database'.
Hard/Safest Method
This is the most time consuming method. I recommend do this in a local integration branch first, pushing it to a remote integration, and then production.
Open the migration file, ie 20160914173357_MyNewMigration.cs.
Drop all indexes in order
Drop/Add/Edit table schemas
Add all indexes back.
For either method, just be sure to test and test again.
Do not modify ApplicationDbContextModelSnapshot. It is a design-time artifact, and should only be modified in the case of a merge conflict.
To update the model, always use data annotations or the fluent API.
For more information on the EF Migrations workflow, see Code First Migrations. It's for EF6, but most of the information is still relevant.
When I Add-Migration, I get the appropriate DbMigration class with the Up / Down methods, where I am able to make schema changes and (with the use of the Sql() method) can make data/content changes as well.
I'd like to be able to make content changes per migration using the database context. I understand that I could use the Seed method in a Configuration class, but my understanding is that I can only wire up one Configuration with my initializer.
I'd prefer to have a UpCompleted()/DownCompleted() methods that would provide access to the db context after the migration completed. This would enable writing incremental data/context change "scripts" in a manner that would be less prone to errors than using the Sql() method.
Am I missing something? Is this possible?
Thanks!
That doesn't really work because the context only has your most recent model - which can only be used to access the database once the most recent migration has run (which is effectively what Seed achieves).
For an example of how this idea breaks, if you moved a property from one class to another then seed logic from older migrations would no longer compile. But you couldn't change it to use the new property because the corresponding column wouldn't exist in the database yet.
If you want to write this kind of seed/data-manipulation logic, you need to put it at the end of the Up/Down methods and use the Sql method to perform it using raw SQL.
~Rowan
On play 1.0 when we change a variable type or for example changing from #OneToMany to #ManyToMany in a Model Play was handling the change automatically but with play 2.0 evolution script drop the database. There is any way to make Play 2.0 apply the change without dropping the DB ?
Yes, there is a way. You need to disable automatic re-creation of 1.sql file and start to write own evolutions containing ALTERS instead of CREATES - numbering them with 2.sql, 3.sql etc.
In practice that means, that if you're working with single database you can also just... manage the database's tables and columns using your favorite DB GUI. The evolutions are useful only when you can't use GUI (host doesn't allow external connections and hasn't any GUI) or when you are planning to run many instances of the app on the separate databases. Otherwise manual writing the statement will be probably more complicated than using GUI.
Tip: sometimes, if I'm not sure if I added all required relations and constraints into my manual evolutions I'm deleting them (under git controlled folder!) and running the app with Ebean plugin enabled and saving proposed 1.sql but I'm NOT applying the changes. Later using git I'm reverting my evolutions and compare with saved auto-generated file and convert CREATE statements to the ALTERs. There's no better option for managing changes without using 3-rd part software.
I am using RavenDb across multiple projects and solutions to access three different databases that are all part of the same product. For instance, I have multiple MVC projects that fetch user info and some data out of the 'web' centric database and the 'backend' database, using '-' for the id override (but I need this only for a subset of classes in the 'web' db). And then I have another 'backend' database that is used by services (as well as the MVC projects). And finally a third temp/scratch database I use by another set of services to build the backend db. And of course, all of these are being accessed from different class libraries and even console test, seed, and integration test apps.
Managing all of these is becoming quite a nuisance. Every time I create a new console app or class library that access the db, I have to setup config and raven packages for each project, make sure indexes are built, etc.... Not to mention running update on all nuget updates, or in my case, installing a new unstable version of the server/client binaries.
Is there an easier way to manage this?
I tried to abstract the DocumentStore creation and initialization, as well as index creation into it own project and reference that. But the other projects then had to manually add newtonsoft.json (and nlog) from the package directory.
As well, I am getting the following when I try and abstract the DocumentStore into a class with a static property:
StackTrace of un-disposed document store recorded. Please make sure to dispose any document store in the tests in order to avoid race conditions in tests.
Anyone have any thoughts on handling these issues?
Thanks
I don't think that the manual addition of the references is a big issue, but you can add the actual nuget references as well.
Note that the DocumentStore not disposed error is something that only happened in the unstable (debug builds), and won't happen on release builds.
I am using NHibernate for a project, and I am absolutely beginner. I am fetching some objects from a table and showing it to a form, where they can be edited. If an user inserts a new object into the table from some other window, I want to show this newly inserted object into the edit window. My application uses tabbed window interface, so user can simultaneously open insert window and edit window at the same time.
So basically what I need is a way to determine if a newly created object exists in the database which is not fetched before by ISession, and if not, then fetch that new object from the database. In other words, I need to synchronize my session with the database, just like flush method, but in the reverse way.
Can anyone help me?
Publish/Subscription method works well for this. Check out the Publishing Events part of Ayende's sample desktop application. Basically after you've added a new item, you publish that information and other parts of your application that subscribed can update their lists accordingly.
You are taking the path to NHibernate Hell.
Be sure to work your infrastructure (ie defining interfaces, defining session management patterns and notification pattern) and isolate these non-business utilies from the rest of your code before using NHibernate to implement them.
Good luck.