I am developing application VS 2008, .NET 3.5 and I am trying to use LINQ To SQL. I drag & drop tables on the designer to generate the .dbml file.
The problem I have that I have some dynamic tables for search indexing.
I know the structure of table, only the application creates new tables like this:
Files_1_1, Files_1_2, ... Files_m_n
DataSearch_1_1, DataSearch_1_2, DataSearch_m_n
In this case, m and n are integers in the name of the table.
I statically define which columns are available but not the name of table, so I need a way to do this on the fly. Of course, this would also have to include associated tables.
I haven't been able to get good idea about it. I would also be satisfied with just being able to generate LINQ To SQL class for this tables.
Has anyone come across a solution to this problem? I have been looking through blog posts and forums for the past one days in vain. Any sample code is great for me.
Link to sql works with stored procedures and the designer will auto create a class for the return type. You could use dynamic sql in your sp and return linq to sql classes.
You could create a stored procedure like below:
CREATE PROCEDURE spGetFiles
(
#TableName
)
AS
EXEC('SELECT * FROM " + #TableName)
Then in the Visual Studio O/R designer, select the SP from the server explorer and drag it into the designer window in the same way that you add tables. A method with the same name as your SP will be created on your data context class and a class called something like spGetFilesReturnType will be created (i may have got this naming slightly wrong but you get the idea). You then just call the datacontext method with the table name as a string parameter and collections of spGetFilesReturnType objects will be returned.
Related
Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
I'm trying to create a program which will generate a SQL database schema including tables, view, keys, indexes, triggers, etc... like:
CREATE TABLE TableName(....) ....
CREATE VIEW ViewName(...) ....
I know this is possible because SQL Server Management Studio does it (generate script command). However, how does it do it?
UPDATE: I forgot to mention about permissions: I'm an owner of database (in most cases) but I'm not sys-admin. Would there be any difference?
If you are targeting SQL Server only, SMO is very powerful. This is the library that SQL Server Management Studio uses, and contains classes to convert database objects into scripts.
The scripting example here is a great place to start.
for list of tables:
foreach (DataRow row in schemaTbl.Rows)
{
listBox.Items.Add(row["TABLE_NAME"]);
}
for columns from perticular table
object[] objArrRestrict;
objArrRestrict = new object[] {null, null, "Customers", null};
DataTable schemaCols;
schemaCols = con.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, objArrRestrict);
//List the schema info for the selected table
foreach (DataRow row in schemaCols.Rows)
{
listBox.Items.Add(row["COLUMN_NAME"]);
}
Queries of database structure vary by sql server version.
The 2008 R2 page is here, which links to a TABLES page, which links to a sys.tables page, which links to a sys.objects page.
The sys.objects page has relevant samples. This only gets you the table. There are other system objects for column, triggers, views, ...
If you truly mean generate you might want to look into Entity Framework / Code first approach that will essentially boostrap your db for you (Tables, etc).
I am working at implementing a search feature into my MVC3 application. I'm looking to pass two parameters into and execute a stored procedure that will look basically something like this:
create procedure MyProc
(
#FirstParam nvarchar(50),
#SecondParam nvarchar(20)
)
as select * from MyTable where #FirstParam like #SecondParam
MyTable has about 30 fields that will be returned for each object and I need to create a procedure like this for several tables, so I am trying to avoid using a SqlDataReader and converting the returned Sql data to C#.
I would like to use something like this method but I am not sure if this can be done with multiple parameters.
Ideally I would like to use EF4, but I have not found any good information on executing stored procedures while using EF4.
Any insight on the most painless way and/or best practice for executing this task will be greatly appreciated.
My sugestion is use dynamic linq (and here, and here). You can pass valid linq expressions as regular strings:
var column = "Name";
var value = "Marvin";
var query = DbCtx.MyEntity.Where("{0} == #1", columnName, value);
The benefits (IMO) is that you can keep the search logic in the application and, if you need to do this for many tables, you can create a T4 template to generate the bootstrap code for you.
What you are suggesting can indeed be done through parameters, and you should be using an ORM like EF4 for you data access. Like most ORM that have support for stored procedure, you can indeed pass multiple parameters to the stored procedure.
The issue you will find, however, is that you can't have dynamic column names in SQL Server (or any other SQL database that I am aware of) - you can't give a column name in a variable.
You will need to use dynamic SQL to achieve this, either within the stored procedure or otherwise.
I'm working with a legacy application which I'm trying to change so that it can work with SQL CE, whilst it was originally written against SQL Server.
The problem I am getting now is that when I try to do dataAdapter.Update, SQL CE complains that it is not expecting the SELECT keyword in the command text. I believe this is because SQL CE does not support batch SELECT statements.
The auto-generated table adapter command looks like this...
this._adapter.InsertCommand.CommandText = #"INSERT INTO [Table] ([Field1], [Field2]) VALUES (#Value1, #Value2);
SELECT Field1, Field2 FROM Table WHERE (Field1 = #Value1)";
What is it doing? It looks like it is inserting new records from the datatable into the database, and then reading that record back from the database into the datatable? What's the point of that?
Can I just go through the code and remove all these SELECT statements? Or is there an easier way to solve my problem of wanting to use these data adapters with SQL CE?
I cannot regenerate these table adapters, as the people who knew how to have long since left.
It is just updating the object with the latest values from the database, after an update. Always seemed a little unecessary to me but hey...
These are a nuisance from a maintenance point of view - if you have the option, you'll save yourself a lot of hassle by abstracting this all out to a proper data layer.
allows that the field values might be altered by trigger(s) on the table. Sensible enough, I'd have thought, in auto-generated boilerplate.
though the select statement is a tad whacky to assume that field1 is the primary key... but maybe the autogen code makes sure it is before generating this bit of code.
I have a customer that has a SQL database on a hosted server; call the db "myDatabase".
The hosting co. has locked down object explorer - I can't see myDatabase in the database listed (I see tempdb and master). However, if I "use myDatabase" and then "select * from myTable", all works fine.
Since we have no access to object explorer, I can't right click and generate scripts. I thought that I might be able to use SMO to accomplish what I want, but when I attempt something similar to this:
Server myServer = new Server(conn);
Database myDB = server.Databases["myDatabase"];
Table myTbl = myDB.Tables["myTable"];
It fails - myDB is null (when I iterate through the databases collection, as expected, I only see master and tempdb - the db's I can see in object explorer). It obviously has to do with security - if I can't see the table in object explorer, it won't let me access it through SMO. Anyone have any ideas of a workaround or alternate method to allow me to generate a script?
Thx!
I haven't looked at the SMO code, but have you tried using the constructor on the database object? Maybe you can access it directly.
Database myDB = new Database(myServer, "myDatabase");
Is the myDb.Tables collection empty? Could it be that you are referencing it using the wrong name?
One option you could try is to use Linq2Sql to generate a model of the database. You can then use the model to create a new database that should be more or less identical to the original. Look up the DataContext.CreateDatabase method for more info.
Another option would be to list all tables using the following query:
select * from sys.tables
And then listing all columns in the tables using the following:
select * from sys.columns where object_id = (object id from the previous query)
This will give you all tables and columns defined in your database and should be enough to create the database structure. In addition you have system views for other objects defined as well.
I've created a stored procedure similar to the one below (I'm using this cut down version to try and figure our the problem).
CREATE PROCEDURE bsp_testStoredProc
AS
BEGIN
CREATE TABLE #tmpFiles
(
AuthorName NVARCHAR(50),
PercentageHigh INT
)
-- Insert data into temp table
SELECT AuthorName, PercentageHigh FROM #tmpFiles
ORDER BY PercentageHigh DESC
DROP TABLE #tmpFiles
RETURN 0
END
From my C# code in VS2008, I'm trying to use the Query component with the Use Existing Stored Procedure option to connect this up to a DataTable / DataGridView to display the results.
However, because I'm selecting from a temporary table, in the Query component properties Visual Studio does not display any columns being returned from the stored procedure. I assume that it has trouble determining the data types being used since the SP is not based on a real schema.
Connecting to different stored procedures that select from real tables do show the columns correctly.
Does anyone know away around this? Is there some sort of hint I can add somewhere to explicitly state what sort of data will be returned?
Thanks in advance.
For info, you might consider using a "table variable" rather than a temporary table (i.e. #FOO rather than #FOO) - this might help a little, and it certainly helps a few tempdb issues.
With temporary tables - no there is no way of explicitly declaring the SPs schema. I would perhaps suggest using a simplified version of the SP while you generate your wrapper classes - i.e. have it do a trivial SELECT of the correct shape.
Alternatively, I would use LINQ to consume a UDF, which does have explicit schema.