I know NHibernate is an ORM and it isn't normally used to create tables but I also know that NHibernate is able to create an entire database given some mappings.
I would like to know if there is an obscured API that I could use to dynamically create/alter/delete tables. I could do it with ADO.Net but I would like to abstract the code for creating tables for different databases (MS SQL, MySQL, etc.)
Precision 1: The problem with CreateSQLQuery is that I would have to rewrite the method for creating a table for different SQL servers (MS SQL, MySQl, etc.) It has no advantages over ADO.Net. When NHibernate generates the database from mappings it generates for any SQL servers... that is what I'm looking for. What is the code that is executed when NHibernate generates a database from mappings... is this code available/public?
Yes you can :)
You create dynamically a Type corresponding to the class to be mapped. And then generate a mapping.
The important classes to look in NH source code are in the Nhibernate.Mapping namespace : PersistentClass, RootClass.
Here is a sample :
https://nhibernate.info/blog/2008/11/16/mapping-source-how-map-a-class-without-use-nothing.html
I have used this "API" to generate dynamically Tables.
There isn't a specific API to dynamically create/alter/delete tables. Depending on what you need to do and when you want these actions to happen you have the following options:
Use the tag in the xml mapping files to perform whatever action you want on the database just after your schema is generated
Use named queries and in the mapping files to create SQL statements to run from your code. (I have never tried these with create/alter/delete table commands but its worth to try).
Use the Session.CreateSQLQuery() method to execute a native SQL command. (Again as the previous option I have never tried it with create/alter/delete table commands but I believe its worth to try).
You could use the schema object.
You need to configure NHibernate and using the schema object call create. the two boolean values will either drop the database and recreate it or just output it to the console.
VB.Net
Public Sub CreateDatabaseSchemaFromMappingFiles()
Dim cfg As New NHibernate.Cfg.Configuration()
cfg.Configure()
Dim schema As New NHibernate.Tool.hbm2ddl.SchemaExport(cfg)
schema.Create(True, False)
End Sub
Related
I have a webservice which tries to connect to a database of a desktop accounting application.
It have tables with same name but with different schema names such as:
[DatabaseName].[202001].[CustomerCredit]
[DatabaseName].[202002].[CustomerCredit]
.
.
.
[DatabaseName].[202014].[CustomerCredit]
[DatabaseName].[202015].[CustomerCredit]
[DatabaseName].[202016].[CustomerCredit]
...
..
[DatabaseName].[2020xx].[CustomerCredit]
Schema name is in format [Year+IncrementalNumber] such as [202014], [202015],[202016] and etc.
Whenever I want to query customer credit information in database, I should fetch information from schema with biggest number such as [DatabaseName].[202016].[CustomerCredit] if 202016 is latest schema in my db.
Note:
Creation of new schema in accounting application database have no rules and is completely decided by user of accounting application and every instance of application installed on different place may have different number of schemas.
So when I'm developing my webservice I have no idea to connect to which schema prior to development. In run-time I can find correct schema to query from its tables but I don't know how to manage to fetch table information with correct schema name in query.
I ususally creat a linq-to-sql dbml class and use its definitions to read information from db but I don't know how to manage schema change in this way?
DBML designer manage Scehma names like this:
[global::System.Data.Linq.Mapping.TableAttribute(Name="[202001].CustomerCredit")]
However since my app can retrieve schema name in run time, I don't know how to fix table declaration in my special case.
It is so easy to handle in ADO.NET but I don't know its equivalent in Linq2SQL:
select count(*) from [" + Variables.FinancialYearSchemaName + "].CustomerCredit where SFC_Status = 100;
Ultimately, no: most ORMs do not expect the schema change to vary at runtime, so most - including EF and LINQ-to-SQL do not support this scenario. One possible option would be to have different connection strings, each with different user accounts, that each has a different default schema configured at the database - and intialize your DB-context with a connection-string or connection that matches the required account. Then if EF asks the RDBMS for [CustomerCredit], it will look first in that account's schema ([202014].[CustomerCredit]). You should probably avoid having a [202014].[CustomerCredit] in that scenario, to prevent confusion. This is, however, a pretty hacky and ugly solution. But... it should work.
Alternatively, you would have to take more control over the data access, essentially writing your own SQL (presumably with a token replacement for the schema, which has problems of its own).
That schema is essentially a manual partitioning of the CustomerCredit table. The best solution would one that makes partitioning transparent to all users. The code shouldn't know how the data is partitioned.
Database Solutions
The benefit of database solutions is that they are transparent or almost transparent to users and require minimal maintenance
Table Partitioning
The clean solution would be to use table partitioning, making the different partitions transparent to all users. Table partitioning used to be an Enterprise-only feature but it became available in all editions since SQL Server 2016 SP1, even Express. This means it's free in all versions still in mainstream support.
The table is partitioned based on a function (eg a date based function) and stored in different files. Whenever possible, the query optimizer can check the partition boundaries and the query conditions and use only the file that contains the relevant data. Eg in a date-partitioned table, queries that contain a date filter can search only the relevant partitions.
Partitioned views
Another option, available since 2000 at least, is to use partitionend views, essentially a UNION ALL view that combines all table partitions, eg :
SELECT <select_list1>
FROM [202001].[CustomerCredit]
UNION ALL
SELECT <select_list2>
FROM [202002].[CustomerCredit]
UNION ALL
...
SELECT <select_listn>
FROM Tn;
EF can map entities to views instead of tables. If the criteria for updatable views are met, the partitioned view itself will be updatable and any modifications will be made to the correct table.
The query optimizer can take advantage of CHECK constraints on the tables to search only one table at a time, similar to how partitioned tables work.
Code solutions
This requires raw SQL queries, and a way to identify the correct table/schema each time a change is made. It requires modifications to the application each time the table partitioning changes, whether those are code modifications, or changes in a configuration file.
In all cases, one query can only read from one table at a time
Keep ADO.NET
One possibility is to keep using ADO.NET, replacing the table/schema name in a query template. The code will have to map to objects if needed, the same way it already did.
EF Raw SQL
Another, is to use EF's raw SQL features, eg EF Core's FromSqlRaw to query from a specific table , the same way ADO.NET would. The benefit is that EF will map the query results to objects. In EF Core, the raw query can be combined with LINQ operators :
var query=$"select * from [DatabaseName].[{schemaName}].[CustomerCredit]"
var credits = context.CustomerCredits
.FromSqlRaw(query)
.Where(...)
.ToList();
Dapper
Another option is to use Dapper or another micro-ORM with an ad-hoc query, similar to ADO.NET, and map the results to objects:
var query=$"select * from [DatabaseName].[{schemaName}].[CustomerCredit] where customerID=#ID";
var credits=connection.Query<CustomerCredit>(query,new {ID=someID});
I am proficient in SQL but not so much in C#. Recently a web application has broke. I am trying to find the data in the SQL database that is entered through the web application. I am confused about where the SQL table and fields are in var query 1 and 2. See attached image.
This looks like Entity Framework, and it would depend on how the mappings are setup, this is usually done either with an EDMX, or using code first with fluent mappings.
So you'll have to look at your mappings, to see what
_ICL_RESENTS_INCOMEDTLS,
_ICL_RESENTS_PAYMENTs,
CDCLIENTS
entities are mapped to which tables. This mapping should tell you what the underlying tables are.
I am migrating an existing application that uses ADO.Net to .Net 4+ with Linq2SQL. The problem is that the application's database contains a table that is customized at runtime using a GUI designer, i.e. the table initially contains the primary key (Id) and 3 other columns, but then the user designs the data that will be tracked in the application using a GUI designer which in turn modifies the structure of this table adding the columns to accommodate the need. The designer also records the structure of this table in a meta-data table that describes these custom columns.
The current application builds SQL strings to build queries. How can I handle querying from this table using Linq2SQL? Is using context.ExecuteQuery<> the only way to do it?
I believe you can use dynamic.cs to get what you are looking for. Might be better to use stored procedures and have the dynamic sql done in the sprocs. Here is the link to dynamic.cs with examples.
dynamic.cs
My application currently uses ado.net to access the database.
It allows users to configure dashboards by passing custom sql. The custom sql includes joins on multiple tables and the columns of every table are included in the result.
We are migrating from ado.net to entity framework 4.
How do I execute the same queries using entity framework?
Also other code in the application requires firing custom complex join queries on the database. This is done by developers.
Yes you can use inline queries and even stored procedue in entityframework
see example for query http://msdn.microsoft.com/en-us/library/bb738451
see example for stored procedure http://msdn.microsoft.com/en-us/library/bb896334.aspx
If you have dynamic queries you cannot execute them through EF. EF works in strongly typed manner so it expects that you created the type with correct properties (with correct types) at design time (you can create the type at runtime as well but it requires you to create dynamic assembly, emit IL, etc.).
Use your old approach for this type of queries.
I have an application where I create database's dynamically in a SQL Server using Server Management Objects through my application.
I want to use the Entity Framework to access this database when it has been created, is this possible? As I can not generate Entity classes from a database in VS. I do have the structure of the database of course.
So is it possible to create the Entity classes manually and is that a do-able task?
Yes, it's completely possible. You can even manipulate the generated code if you want.
What you might want to take a look is the EDMX XML specification.
In that file you specify the underlying database, views, functions, procedures and the like, as well as the desired objects. Take a look at MSDN in order to have more information.
Paulo is right for EF 1 (+1). For EF 4, I'd suggest using code-only modeling instead.