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
Related
I'm a bit confused by SqlConnection's ChangeDatabase(string databaseName).
I thought database names didn't have to be unique if they aren't in the same schema, for example I can have dbo.DatabaseName and hr.DatabaseName .
Every example of ChangeDatabase that I have seen though only uses the database Name ... is that just laziness and I can actually provide the full name by using
"[dbo].DatabaseName" as a parameter? Or is there something more to it ?
In Microsoft SQL Server, databases are not associated with schemas the way you think.
If you want to see a parent-child relation between them, I would say the database is the parent.
In a database, multiple schemas can exist. Once you create them, you can then define tables and other database objects (even users) that are part of one of the schemas you defined at database-level.
So, the ChangeDatabase method does nothing but executing a "USE {DBNAME}" statement in T-SQL.
Take a look: USE (Transact-SQL)
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.
We have 2 different databases DB1 and DB2 with tables in DB2 referring to tables in DB1.
We are looking into the possibility of using SYNONYMS with read-only access in DB2 and use EntityFramework to refer to these SYNONYMS as tables in DB2.
Since currently EF doesn't span across multiple databases, after reading this article (http://rachel53461.wordpress.com/2011/05/22/tricking-ef-to-span-multiple-databases/) we are one step ahead, but, we want to only have read-only access to the newly created SYNONYMS.
Any help is greatly appreciated!
You can create a schema for your synonym (such as "EntityFramework" or "EF" for simplicity). Create a role for your schema, naming it something to the tune of "EntityFrameworkUser".
Now there are two paths, here- this first one if you only ever have SELECT access, or the second one if you may also need EXECUTE access.
FIRST:
Going into the properties of your EntityFramework schema, you can navigate to Permissions, search for and add your EntityFrameworkUser role, and check only SELECT in the list of permissions below.
SECOND:
Going into the properties of your EntityFrameworkUser role, you can navigate to Securables, go to "Search..." for securables, use 'All objects belonging to the schema' with your EntityFramework schema.
For each of the objects showing up as a result, which should just be Synonyms (unless you also made new tables/SPs in the "EntityFramework" schema), you can grant access to "Select", and leave everything else unchecked unless you want the user to have more or less power with those objects.
REGARDLESS:
This will allow you to have visibility to the table without write/execute access. Assign whichever server user needs this readonly access, and add them to the "EntityFrameworkUser" role. In my case, there's a "WebApplication" and a "DesktopApplication" user, both of which are assigned to the "EntityFrameworkUser" role.
This should solve your issue of visiblity, while restricting write and execute access within the system.
I have one SQL Server with multiple databases. Database1 has a table with a reference to IDs that are stored in a table on Database2. Not sure if it's possible, but could I configure NHibernate (Fluent NHibernate specifically) to saturate an object pulling data from multiple databases?
I'm not concerned about writing to these tables, I'm just trying to ORM the objects to display in an data viewing application.
I realize this isn't an ideal database situation, but it's what I was given to work with.
The usual answer to db-specific query structures, like cross-DB queries, is to create a view on the "local" DB (that NH connects to) that will perform the cross-DB query and return the joined results. You can also have a repository-per-DB and develop some means to query the records from each DB and join them manually.
One thing that will also work; the table property of each mapping is just a string, and could be anything; NHibernate just takes that and plugs it in wherever it needs to reference the table name. So, you could try specifying the tables in the mappings using their fully-qualified names: ConnectedDB..LocalTable, OtherDB..RemoteTable. It might be considered a hack, but it's also rather elegant in a way; your program doesn't even have to know there are multiple databases in the persistence schema.
I have two databases, one is an MS Access file, the other is a SQL Server database. I need to create a SELECT command that filters data from the SQL Server database based on the data in the Access database. What is the best way to accomplish this with ADO.NET?
Can I pull the required data from each database into two new tables. Put these in a single Dataset. Then perform another SELECT command on the Dataset to combine the data?
Additional Information:
The Access database is not permanent. The Access file to use is set at runtime by the user.
Here's a bit of background information to explain why there are two databases. My company uses a CAD program to design buildings. The program stores materials used in the CAD model in an Access database. There is one file for each model. I am writing a program that will generate costing information for each model. This is based on current material prices stored in a SQL Server database.
My Solution
I ended up just importing the data in the access db into a temporary table in the SQL server db. Performing all the necessary processing then removing the temporary table. It wasn't a pretty solution but it worked.
You don't want to pull both datasets across if you don't have to do that. You are also going to have trouble implementing Tomalak's solution since the file location may change and might not even be readily available to the server itself.
My guess is that your users set up an Access database with the people/products or whatever that they are interested in working with and that's why you need to select across the two databases. If that's the case, the Access table is probably smaller than the SQL Server table(s). Your best bet is to pull in the Access data, then use that to generate a filtered query to SQL Server so that you can minimize the data that is sent over the network.
So, the most important things are:
Filter the data ON THE SERVER so that you can minimize network traffic and also because the database is going to be faster at filtering than ADO.NET
If you have to choose a dataset to pull into your application, pull in the smaller dataset and then use that to filter the other table.
Assuming Sql Server can get to the Access databases, you could construct an OPENROWSET query across them.
SELECT a.*
FROM SqlTable
JOIN OPENROWSET(
'Microsoft.Jet.OLEDB.4.0',
'C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\Northwind.mdb';'admin';'',
Orders
) as b ON
a.Id = b.Id
You would just change the path to the Access database at runtime to get to different MDBs.
First you need to do something on the server - reference the Access DB as a "Linked Server".
Then you will be able to query it from within the SQL server, pulling out or stuffing in data however you like. This web page gives a nice overview on how to do it.
http://blogs.meetandplay.com/WTilton/archive/2005/04/22/318.aspx
If I read the question correctly, you are NOT attempting to cross reference across multiple databases.
You need merely to reference details about a particular FILE, which in this case, could contain:
primary key, parent file checksum (if it is a modification), file checksum, last known author, revision number, date of last change...
And then that primary key when adding information obtained from analysing that file using your program.
If you actually do need a distributed database, perhaps you would prefer to use a non-relational database such as LDAP.
If you can't use LDAP, but must use a relational database, you might consider using GUID's to ensure that your primary keys are good.
Since you don't give enough information, i'm going to have to make some assumptions.
Assuming:
The SQL Server and the Access Database are not on the same computer
The SQL Server cannot see the Access database over a file share or it would be too difficult to achieve this.
You don't need to do joins between the access database and the sql server, only use data from teh access database as lookup elements of your where clause
If the above assumptions are correct, then you can simply use ADO to open the Access database and retrieve the data you need, possibly in a dataset or datatable. Then extract the data you need and feed it to a different ADO query to your SQL Server in a dynamic Where clause, prepared statement, or via parameters to a stored procedure.
The other solutions people are giving all assume you need to do joins on your data or otherwise execute SQL which includes both databases. To do that, you have to use linked databases, or else import the data into a table (perhaps temporary).
Have you tried benchmarking what happens if you link from the Access front end to your SQL Server via ODBC and write your SQL as though both tables are local? You could then do a trace on the server to see exactly what Jet sends to the server. You might be surprised as to how efficient Jet is with this kind of thing. If you're linking on a key field (e.g., and ID field, whether from the SQL Server or not), it would likely be the case that Jet would send a list of of the IDs. Or you could write your SQL to do it that way (using IN SELECT ... in your WHERE clause).
Basically, how efficient things will be depends on where your WHERE clause is going to be executed. If, for instance, you are joining a local Jet table with a linked SQL Server table on a single field, and filtering the results based on values in the local table, it's very likely to be extremely efficient, in that the only thing Jet will send to the server is whatever is necessary to filter the SQL Server table.
Again, though, it's going to depend entirely on exactly what you're trying to do (i.e., which fields you're filtering on). But give Jet a chance to see if it is smart, as opposed to assuming off the bat that Jet will screw it up. It may very well require some tweaking to get Jet to work efficiently, but if you can keep all your logic client-side, you're better off than trying to muck around with tracking all the Access databases from the server.