I have an existing NHibernate 2.1.2.4000 mapping that uses the mapping syntax:
<database-object>
<create>
CREATE VIEW View_Register AS ... (truncated for example)
</create>
<drop>
DROP VIEW View_Register
</drop>
</database-object>
When the database schema gets created, I use:
new SchemaExport(_configuration).Execute(true, true, false, aSession.Connection, tw);
The third parameter in the method above is 'dropOnly', which is obviously set to false.
In the past, my schema is created and the 'View_Register' is created successfully. Now, I'm re-running the schema generation, and the DROP is called at the beginning of the schema generation, but the CREATE is never called. I've confirmed this with multiple SQL profilers including the NH profiler.
Using explicit dialect declarations doesn't seem to work either:
<dialect-scope name="NHibernate.Dialect.MsSql2000Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2005Dialect"/>
<dialect-scope name="NHibernate.Dialect.MsSql2008Dialect"/>
Any ideas folks?
Thanks,
David
I'm a complete idiot...
My View_Register mapping/view was completely fine, and was not my problem.
A different view was failing to create BEFORE View_Register because of a renamed table. Apparently, subsequent database-object/create calls are aborted on any ADO exception thrown by a previous create.
Good to know, but I feel silly for answering my own question!
Related
I recently used - EXEC sp_rename '<source table name>', '<destination table name>' to rename an existing table and want to execute the same on one of our live server. Is there any issue in using this procedure to rename a table?. I am asking this because one of our DBA says there will be problems in using this procedure on live server.
Is nothing referencing the table you're renaming? That would be the only instance where I would think renaming the table would not have an impact. If the table was not referenced by anything however, what would be the purpose of the table?
you can read more about sp_rename here:
http://msdn.microsoft.com/en-us/library/ms188351.aspx
Specifically note the following:
Renaming an object such as a table or column will not automatically
rename references to that object. You must modify any objects that
reference the renamed object manually. For example, if you rename a
table column and that column is referenced in a trigger, you must
modify the trigger to reflect the new column name. Use
sys.sql_expression_dependencies to list dependencies on the object
before renaming it.
There is no major issue with renaming the table using that procedure. The only thing you need to remember is that while that command is being executed, the locks that are applied on that table won't allow you to query the data, but that should only take only a couple of milliseconds, so you should be fine.
P.S. Don't forget to modify your views, procedures, functions etc :)
Below is the only caution as described inthe microsoft official web site.
Changing any part of an object name can break scripts and stored procedures. We recommend you do not use this statement to rename stored procedures, triggers, user-defined functions, or views; instead, drop the object and re-create it with the new name.
More details at : http://msdn.microsoft.com/en-us/library/ms188351.aspx
EXEC sp_rename is recommended only when we sure that all the depended SP, View function are not get affected. Make sureyou changed or deleted the depended objects.
Perhaps your DBA can share the details of his/her concerns. Renaming a table will of course be a breaking change for any objects that reference the table so you'll need to perform due diligence to ensure dependent objects are changed to use the new name. The rename operation will also require a short schema modification lock and void existing referencing cached plans, so be aware of this if the table is heavily used.
I am trying to build a dependency tree for a database by tracing object relationships through sys.sql_expression_dependencies (or I might use sys.dm_sql_referenced_entities instead if it's the only way to accomplish this).
I notice that for some referenced objects, I get the referenced_entity_name but not the referenced_schema_name or (crucially) the referenced_id. Looking through Microsoft's page on sys.sql_expression_dependencies I see that these columns can be NULL when "The schema of the referenced entity depends on the schema of the caller and is resolved at run time." Looking into the referencing stored procedure, I see that it refers to the referenced object as simply MyObject, not dbo.MyObject. (Virtually all of this database is in the dbo schema, so some people - myself included - have sometimes lazily neglected to include explicit schema references). I tried changing the procedure definition to explicitly reference dbo.MyObject, and then looked again in sys.sql_expression_dependencies, and I do indeed see the referenced_schema_name and the referenced_id that were previously missing.
I can't, at the moment, fix all objects in the database so that they make all references explicitly by schema. So, my question is: where the Microsoft page says "The schema of the referenced entity depends on the schema of the caller and is resolved at run time" does this simply mean that the SQL engine will always infer that the schema of the referenced object is the same as the schema of the referencing object? If so, I can then use MyReferencingObjectSchema + MyReferencedObjectSchema to look up the object_id for the referenced object and continue building my tree. Or is it more complicated than that?
It's more complicated than that, I'm afraid. It will look for an object with the right name in the connection's default schema as well. This is why you usually don't have to put the schema name in for dbo - that's the usual default schema.
What order it looks for things I don't know - default or current first - but that should be easily testable.
I'm getting back into NHibernate and I've noticed a new configuration property being used in examples: SchemaAutoAction. I cant seem to find documentation on what the various settings mean. The settings / my guesses as to what they mean are:
Recreate -- Drop and recreate the schema every time
Create -- If the schema does not exist create it
Update -- issue alter statements to make the existing schema match
the model
Validate -- Blow up if the schema differs from the model
Is this correct?
SchemaAutoAction is the same as schema-action mapping attribute.
As per docs:
The new 'schema-action' is set to none, this will prevent NHibernate
from including this mapping in its schema export, it would otherwise
attempt to create a table for this view
Similar, but not quite. The SchemaAutoAction is analogous to the configuration property hbm2ddl.auto, and its values are:
Create: always create the database when a session factory is created;
Validate: when a session factory is created check if the database matches the mappings and throw an exception otherwise;
Update: when a session factory is created issues DDL commands to update the database if it doesn't match the mappings;
Recreate: always creates the database and drop it when the session factory is disposed.
I know databases aren't supported by CREATE SYNONYM, but I'm looking to achieve the functionality this would provide.
We've got Database A which contains views to tables on Database B. The trouble is "Database B" isn't always called "Database B". We use database projects for deployments, which at the moment fall over with an "Invalid Object Name" error if there isn't a "Database B".
The workaround at the moment is to open up the .dbschema file and do a find and replace. I guess another option would be to create a load of table synonyms.
What's the best way of changing the database a number of views reference without changing each view individually?
Thanks
Synonyms are a good way to do this. You have to create the synonyms at the object level though (as you've discovered). An easy way to do this would be to write a script that runs through the list of tables in DatabaseB (from your example) and creates a synonym for each one in DatabaseA. Keep the name of the synonym the same so the code in your views doesn't have to change. For instance, you you have tbl_a, tbl_b, and tbl_c in DatabaseB, you'd want your script to eventually do the following:
create synonym [otherDb].[tbl_a] for [DatabaseB].[schemaB].[tbl_a]
create synonym [otherDb].[tbl_b] for [DatabaseB].[schemaB].[tbl_b]
create synonym [otherDb].[tbl_c] for [DatabaseB].[schemaB].[tbl_c]
Now, in your view code, you'll always use [otherDb].[tbl_a], [otherDb].[tbl_b], and [otherDb].[tbl_c]. Hope this makes sense.
Last year I helped my current client with the implementation of a very similar design. We wrote a set of functions and stored procedures which generate the views automatically. Whenever you need to change the target database it generates the code to drop and recreate all of the views.
The code wasn't too difficult. It just uses the system tables to generate view code. I also wrote a Powershell prototype that uses SMO to do the same thing. The key is to have it automated to the point of requiring a single call so that you can do it easily and accurately.
We also included an exception table that used a pattern match of tables to exclude from view generation. It included a schema column and a table name column, each of which accepted LIKE patterns, so you could put "my_schema" and "%" to exclude all tables in the my_schema schema.
One master stored procedure accepted a target database name and would generate the entire script. Once the script is generated you can run it in SSMS or have that part automated as well.
This whole thing would be even easier if you just wanted to generate synonyms. We were using views so that we could change column lists, etc. and have the view DB look different than the target DB where needed.
I've built an MVC3 application using the Entity Framework database first approach. I was able to round trip all objects, then needed to make a schema change. After changing the database schema and updating the .edmx, SaveChanges() fails for objects that map to a db table with column changes.
Specifically: Originally I had a table 'project_issue_installation' that had column 'installation_system_id'. I've changed the schema to remove the 'installation_system_id' from 'project_issue_installation', ran an 'update model from database', recompiled and checked the datmodel .edmx. No errors on compilation and the model .edmx looks correct.
When I try to persist a project_issue_installation object, I get a Invalid column name 'installation_system_id' exception.
I've searched the entire solution for 'installation_system_id' and came up with nothing. Can anyone point me to where the app is holding on to that column name?
-Dan
Turned out to be a problem in the db schema, not the EF model. My DBA missed a trigger that was still pointing to the old column.