Entity framework "default schema" in SQL Server? - c#

We have a complete application using Entity Framework. There are 30 tables with many interconnected relationships. All of these tables exist in an SQL Server schema associated directly with this application.
(By "schema" I mean a SQL "namespace", not "schema" as in "the definition of my tables").
For example, this schema is created as:
CREATE SCHEMA [myApp]
Additionally, we have a "master" schema that has data that is common across a few applications. (We use schemas to separate applications within a single database catalog.)
Now, I've been asked to bring up a second instance of our application with its own independent tables. So for example:
CREATE SCHEMA [mySecondApp]
This new schema is to contain all of the same tables and relationships between them as is in the [myApp] schema. It will still be referencing our "master" schema as well.
The problem is it looks like Entity Framework directly references the table by fully qualified name, which includes the schema. (e.g. MyDB.MyApp.table1 and so on). This means that in order to support this scenario I either need to convince IT to give me another catalog, which will need its own real-time-synchronized copy of the master schema data, or I need to get Entity Framework to reference another schema.
Short of literally find/replacing the schema across the entire EF model, then separately maintaining both models (destroying all the benefits of e.g. migrations), how can I do this? Ideally I'd like a variable in which I can hold the schema, which can be set in the Web.config file, which EF will then pick up on and use everywhere, including in migrations and the application itself.
The pipe dream: Change a value in web.config, run Update-Database, and have a ready-to-go schema with all the tables pre-populated as per our migrations and Seed method. Change the value again in web.config and do it again as many times as desired with different schema names. (Note that the master schema references should remain intact - this is why I'm thinking about some kind of variable.)
Of course also, change the value in web.config on the IIS application server and point the app at the other schema. Then I simply setup multiple deploy profiles with Web.config transforms for each instance on our IIS.

Related

EF6 Queries Using Wrong Database

I am using Devart dotConnect for MySQL with Entity Framework 6 in a Windows Forms application (.Net Framework 4.8). I'm using the DB first approach with a dynamic connection string. My application can connect to any number of databases all with the same schema, so I am building the connection string based on input from the user. I have used this approach on several other projects and have never encountered this issue before. I have spent the last day searching for someone reporting a similar issue, with no luck.
I've created my EDMX model using an empty database (meaning no data, but full schema) called entity_model. I can create instances of the DBContext-derived entity class, and I can even use the attached database to perform general queries on the attached server (e.g. get a list of installed database). I can even perform SQL queries into the database identified in the connection string (using DbContext.Database.SQLQuery), and the results are what I expect. However, when I try to use the DbSet-derived members of the Entity class, my queries are always being directed at the database that I used to generate the model, regardless of the database identified in the connection string.
Stepping through the code, I can see that the settings in the entity object all look correct (entity.Database.Connection.ConnectionString looks exactly like I would expect, and entity.Database.Connection.Database has the correct database name). However, if I examine the internal query value (DbSet.SQL) for any of the DbSet objects, I get something similar to this:
SELECT
Extent1.ID,
Extent1.Field1,
Extent1.Field2,
Extent1.Field3,
FROM entity_model.table1 AS Extent1
where entity_model is the database that I used to create the model. I've done enough testing to know that the queries are actually being executed against this incorrect database, rather than the one passed in through the connection string.
As I've said, I've used this same technique on other projects and have not run into this issue. I've even stepped through some old code and I can see that the contents of the DbSet.SQL field contains no reference to any database (neither the one used to create the model, nor the one from the connection string). This is what I would expect to see in my new project as well.
Can someone explain to me how EF decides whether to include the schema name in the DbSet.SQL field? This is making me a little crazy.
I've tried this across a number of the 50 or so databases that I have installed on my machine, so I know the problem is not with any particular database.
I've found a solution (actually 2 solutions) to this problem. The basic problem is that EF is using the schema specified in the edmx EntitySet element by default:
<EntitySet Name="table1" EntityType="Self.table1" Schema="entity_model" store:Type="Tables" />
This behavior can be turned off in 2 ways. Either add the following lines to your applications startup code:
using Devart.Data.MySql.Entity.Configuration;
...
var config = MySqlEntityProviderConfig.Instance;
config.Workarounds.IgnoreSchemaName = true;
Or add the following sections to your config file:
inside the configSections element:
<section name="Devart.Data.MySql.Entity" type="Devart.Data.MySql.Entity.Configuration.MySqlEntityProviderConfigurationSection, Devart.Data.MySql.Entity.EF6, Version=8.21.2066.0, Culture=neutral, PublicKeyToken=09af7300eec23701"/>
And then after the configSections element:
<Devart.Data.MySql.Entity xmlns="http://devart.com/schemas/Devart.Data.MySql.Entity/1.0">
<Workarounds IgnoreSchemaName="true"/>
</Devart.Data.MySql.Entity>
I found a third option online, and that was to simply delete the schema name from each of the EntitySet elements in the edmx file, but I think that could cause some issues if you ever try to update the model from a database.
I'm hopeful that this answer will prove useful to someone else down the road.

Can I load SimpleMembership classes into EntityFramework?

I've been trying to load the standard ASP.NET SimpleMembership (SM) classes into my EntityFramework (EF) model, but keep running into a few brick walls. I want to use the UserProfile table as a class in my model to bind applications to certain users, then let an admin decide which user can see/edit specific applications.
The way I'm doing it now is running the EF-generated .sql over the .mdf file ASP attaches to the DB at runtime. Then run 'Update Model from Database' in EF. The result is the following pic:
The User class should be replaced with UserProfile (and UserType by Roles), but this won't run because of ambiguity between the EF UserProfile and the SM UserProfile. ASP's internal code can't seem to handle that:
The mapping of CLR type to EDM type is ambiguous because multiple CLR
types match the EDM type 'UserProfile'
I've tried renaming the UserProfile entity to something like aspnet_UserProfile, but it results in EF not being able to find the corresponding table (because that's still named UserProfile and it should because that's where SM reads).
Is this even possible? Or am I approaching this from the wrong angle?
Small side-question: why is the .mdf a standard MVC project uses so small compared to the classes the aspnet_regsql.exe tool adds?
EF doesn't allow you to have class that differs only by namespace. You can rename the entity as you did but change the mapping so the table name is still UserProfile.
See mapping details window. Another option is to let the mapping unchanged (after changing entity name so you have a table name different from 'UserProfile') and specify it in the initialisation of your identity provider WebSecurity.InitializeDatabaseConnection.
The table you see are simplified and allows better integration than the old way to do SQL Membership (aspnet_regsql). If you want more information about new identity and background on membership, see the Introduction to ASP.NET Identity
Note that the Simple Memebership provider comes with :
It was hard to persist membership system data in a non-relational
store.
You can't use it with OWIN.
It doesn't work well with existing ASP.NET Membership providers, and
it's not extensible.
Entity Framework uses only class names to identify the type mapped in EDMX and namespaces are ignored - it is a convention to allow mapping classes from different namespaces to single model. From your description, it seems that you would have two same named entities and because of the reason I mentioned above, it throws the error.
But you can name your classes in BLL differently (You have used classes with the same name - EF uses only class names to identify the type mapped in EDMX (namespaces are ignored)) and rename the entities as the workaround.

entity framework with two databases (completely different schemas )

I am very new to entity framework and I am trying to do something like following scenario.
I am creating ASP.net web from application. That website needs to connect to two databases which the schemas are completely different.
I have no idea how the basic structure should be.
I though of have EF on class library. please guide me with instructions since I have less knowledge.
Since you are using two different databases, the only viable option is to create two separate conceptual models. Even if you would be able to merge two different databases into a single conceptual model, it would be a pain to maintain is the databases are of mentionable sizes.
The two models could reside within the same project, in seprate folders to get different namespaces.
E.g.:
Company.MyApp.DataModel
Company.MyApp.DataModel.Model1
Company.MyApp.DataModel.Model2
Then you could put a new layer on top of these two models which do all the heavy lifting, and could even make them look like one database if you want that, or merge data from entities in both models into a DTO or something similar.
Check out the Repository pattern.
If you think about it, when you create a EDM model with Visual Studio it ask you to give an existing database, and when finished creating the model, it generates an EF connection string, that internally address to the given underlying database connection string.
E.g: metadata=res:///EFTestModel.csdl|res:///EFTestModel.ssdl|res:///EFTestModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\;Initial Catalog=EFTest;Integrated Security=True;MultipleActiveResultSets=True"*
So each model matches only a database, only a connection string.
EF4 still does not support creating one conceptual model which works with N storage models. At least this is not supported with any built-in provider. Perhaps in the future this could be done through a new provider that combines the support of many storages (from the same providers or different).
I havent done enough research on it, but perhaps Windows Server AppFabric (Codename Velocity) could be the bridge to go through this gap.
Note: I have tried even editing manually the xml for the EDM (edmx) to insert a second element inside the tag but it does not match the EDM XML Schema so VS warns about it: Error 10021: Duplicated Schema element encountered.
You are going to use model first approach as the database already exists.
You will need to create two edmx for the two database.
You can create one model project which you can have connection strings for both the edmx in the app.config file and then create your edmx.

What is dbo in dbo.Sometable

In my local or on a dedicated server, when i create a table i see the table name as follows:
dbo.Foo
As i was given a database account from some plesk environment, the tables which were created get the name :
mydbuser.Foo
How does prefix matter for my code? or If i create a table/ restore one from my backup, should i expect weird results?
dbo is the default schema that is assigned to a table when you create a table and don't assign a schema explicitly. A database schema is a way to logically group objects such as tables, views, stored procedures etc. You can read more about schemas here
How does prefix matter for my code?
If you don't specify schema in the code, then it will take dbo as default. Though if you have a table with schema other than dbo, then you will have to specify in your code as well, otherwise it won't execute.
If i create a table/ restore one from my backup, should i expect weird results?
Schemas are not evil. If you specify them correctly, everything should be fine.
dbo
It is schema. If no default schema is defined for a user account, SQL Server will assume dbo is the default schema.
As per MSDN
SQL Server 2005 introduced the concept of database schemas and the
separation between database objects and ownership by users. An object
owned by a database user is no longer tied to that user. The object
now belongs to a schema – a container that can hold many database
objects. The schema owner may own one or many schemas. This concept
creates opportunities to expose database objects within a database for
consumption yet protect them from modification, direct access using
poor query techniques, or removal by users other than the owner.
To create your own Schema, you can use following script:
CREATE SCHEMA [EnterSchemaNameHere] AUTHORIZATION [dbo]
You can use them to logically group your tables, for example by creating a schama for "Financial" information and another for "Personal" data. Your tables would then display as:
Financial.Foo
Personal.Foo

how to use MySQL and MSSQL both in ASp.net application with Entity framework

I've written a ASp.net C# .NET 4.0 application and I've used Ms SQL2008 DB.
It's a 2 tier application... BLL/DAL and UI
I have used
- tables (with multiple index to make the record unique)
- relationals between tables (1 to m relation)
- Entity Framework for Datamodel
- LINQ (update/insert/select/delete)
I haven't used
- Storedprocedures
- Views
- Tsql
- no manual SQL operation
- etc.
So If you see it's very easy setup. The application uses MsSQL2008 DB
so my question is: I need to use MySQL (request of client).
What do I need to do? Since I've used Entitiy Framework I think this should be easy done right?
How can I make that the application can use MySQL / or can support both (my SQL/Mysql).
please advice?
EDMX file consist of three parts:
SSDL - description of the database. This part includes information about used database server
CSDL - description of your classes
MSL - description of mapping between SSDL and CSDL artifacts
If you want to use multiple database servers you must have at least separate SSDL for each of them (if you are going to use different table or column names per database you must also have separate MSL).
When your library is compiled those three parts are extracted into separate files and included as resources to your compiled dll. That are those strange things referenced from EF connection string. You can switch the generation in EF designer and those files will be deployed to your bin directory instead.
The problem with supporting multiple database server is that you need multiple SSDL files. VS and EF designer allows you working with SSDL only within EDMX and each EDMX can have only single SSDL. So your options for supporting multiple DBs are:
Separate EDMX for each server. That makes really big problems because you must synchronize them and you must ensure that CSDL part will be exactly the same.
One CSDL, one MSL, two SSDLs in your project. Again this is really problematic because it means having single main EDMX and separate SSDL (it is XML file) where you will maintain all DB description again.
Only one EDMX for MSSQL server with artifacts deployed to bin directory + separate postprocessing which will take SSDL and creates second one for MySQL automatically. This is imho best option. You need to detect differences in used types between MySQL and MSSQL (you can use trick described by #ChristiaanV to find those differences but make sure you backup your EDMX because you will have to revert it) and write either custom console application, script or XSLT transformation which will convert SSDL for MsSQL to SSDL for MySQL. You will end with one CSDL, one MSL and two SSDLs where the second is autogenerated from the first one.
To make it work at runtime you need MySQL provider for EF - for example the connector mentioned by #ChristaanV and you must reference correct SSDL in connection string for MSSQL and MySQL.
Btw. next time learn which DB customer requires before you develop the application. It is real analysis / requirement failure to develop application for platform customer don't support.
You can install the Mysql .Net connector and in your EDMX file you can select DDL Generation Template = SSDLToMySQL.tt (VS)
It will than generate the sql code based on Mysql.

Categories

Resources