Changing ntext to nvarchar using C# and Entity Framework - c#

I have to add sorting to existing database created in SQL Server. The problem is that this database contains ntext columns that are not supported by LinQ's OrderBy method. The database was written in a code-first approach, so I have access to template of database, but I can't look at ready database working on the server.
I've tried to change string type properties marking them as
[Column(TypeName = "nvarchar(MAX)")]
but then I got a
Sequence contains no matching element
exception which I don't know how to fix.
This is the way that I wanted to sort my data(i got exception right in the below instruction:
MyDatabase.MyTable.OrderBy(x => x.MyRow).Load();
Before I changed TypeName to nvarchar, I've got this error:
Large objects (ntext and image) cannot be used in ORDER BY clauses
Can somebody help me with fixing things up to make possible to sort data from database?
I'll appreciate any kind of help. Thanks in advance!

In T-SQL you can solve this in many ways, may be you can adopt one of them for you too?
ORDER BY (cast MyTextCol as nvarchar(max))
create a view from
this table with that field casted as nvarchar(max) and use it
instead of your table(even in future)
ALTER TABLE myTable ALTER
COLUMN myTextCol nvarchar(max)
The last one solves your problem and takes no time to be made: it's just a metadata operation, nothing will reorganizen in your table for existing rows

Related

How can I load a .Net DataTAble schema from a UDT Table declared in our DB?

I've searched every way I can come up with, but can't find an technique for initializing a DataTable to match a UDT Table declared in our DB. I could manually go through and add columns, but I don't want to duplicate the structure in both places. For a normal table, one option would be to simply issue a "select * where ..." that returns no results. But can something like this be done for a UDT Table?
And here is the background problem.
This DB has a sproc that accepts a Table Valued Parameter that is an instance of the indicated UDT Table declared in the same DB. Most of the UD fields are nullable, and the logic to load the TVP is quite involved. What I hoped to do is initialize the DT, then insert rows as needed and set required column/field values as I go until I'm ready to toss the result to SS for final processing.
I can certainly add the dozen or more fields in code, but the details are still in flux (and may continue to be so for some time), which is one reason I don't really want to have to load all the columns in code.
So, is there a reasonable solution, or am I barking up the wrong tree? I've already spent more time looking for the solution I expected to exist than it would have taken to write the column loading code 100 times over, but now I just want to know if it's possible.
Ok, I was discussing with a friend who is MUCH more SQL savvy than I am (doesn't take much), and he suggested the following SQL query:
"DECLARE #TVP as MyUDTTable; SELECT * FROM #TVP"
This appears to give me exactly what I want, so I'm updating here should some other poor sap want something similar in the future. Perhaps others may offer different or better answers.
Here is an example of how I did this. This style of input/output is something me and a co-worker put together to allow quick and effective use of entity framework on his side and keeps my options open to use all sql toys. If that is the same use as you have you might also like the OUTPUT use I did here. It spits the newly created ids right back at whatever method calls the proc allowing the program to go right on to the next activity withouth pestering my database for the numbers.
My Udt
CREATE TYPE [dbo].[udtOrderLineBatch] AS TABLE
(
[BrandId] [bigint] NULL,
[ProductClassId] [bigint] NULL,
[ProductStatus] [bigint] NULL,
[Quantity] [bigint] NULL
)
and the procedure that takes is as an input
create procedure [ops].[uspBackOrderlineMultipleCreate]
#parmBackOrderId int
,#UserGuid uniqueidentifier
null
,#parmOrderLineBatch as udtOrderLineBatch readonly
as
begin
insert ops.OrderLine
(
BrandId
,ProductClassId
,ProductStatusId
,BackOrderId
,OrderId
,DeliveryId
,CreatedDate
,CreatedBy)
output cast(inserted.OrderLineId as bigint) OrderLineId
select line.BrandId
,line.ProductClassId
,line.ProductStatus
,#parmBackOrderId
,null
,null
,getdate()
,#UserGuid
from #parmOrderLineBatch line
join NumberSequence seq on line.Quantity >= seq.Number
end

How to delete object without retrieving it in EF

We have a table that has a couple of nText columns so looking to delete a rows without retrieving it if possible
Another twist is that we don't know the IDentity value but a couple of other values that identify the row uniquely so examples such as the one below won't work as is
http://blogs.msdn.com/b/alexj/archive/2009/03/27/tip-9-deleting-an-object-without-retrieving-it.aspx
Hoping there's something newer in EF5 to address this without resorting to stored procs ?
Use ExecuteStoreCommand
For example:
databaseContext.ExecuteStoreCommand("DELETE FROM [table] where ... ");

Problem with Insert query to Paradox table using C#

I have Paradox 5.x tables I need to connect to in order to select and update.
I am using OLEDBConnection.
selecting from the tables I have no problem.
while trying to insert into the tables I met a problem when I entered hardcoded the fields names I got an error:
The INSERT INTO statement contains the following unknown field name: ...
so I used OleDbDataReader.GetName(...) to get fields names.
now I use the fields names received from table in order to insert into table and I still get the same error.
I think the problem is with the field name: 'Truck #1 Serial Number'
Table name: 'Vehicles'
I tried using [], ."", .[] and
.[""].
I have read about the need of Borland engine but I'm not sure this is the issue.
Thanks upfront.
-=Noam=-
p.s I cannot change name of tables since its a customer DB I need to connect.
Im adding the C# code I use:
private static string createInsertQueryVehicle(string i_VehicleNumber, string i_VehicleMFG, string i_Truck1SerialNo, string i_Truck2SerialNo, string i_Truck3SerialNo)
{
string tryout = string.Format("INSERT INTO {0} ([{6}], [{7}], [{8}], [{9}], [{10}]) VALUES(RIGHT('{1}',10),'{2}','{3}','{4}','{5}')",
TableName, Vnum, Vinfo, T1Serial, T2Serial, T3Serial, VnumFieldName, VinfoFieldName, T1SerialFieldName
T2SerialFieldName,T3SerialFieldName);
return tryout;
}
at end tryout holds:
INSERT INTO Vehicles ([Vehicle Number], [Vehicle Mfg], [Truck #1 Serial Number], [Truck #2 Serial Number], [Truck #3 Serial Number]) VALUES(RIGHT('000000010001525',10),'קרונות משא','ר40011_1','ר40011_2','')
EDIT:
Just wanted to add my solution at end:
At the end the best solution I could get was to use accesses as the connection point using linked tables to the paradox tables, at end handling it as an accesses DB.....
Hope it helps someone.
You need to use the quoted identifiers while having special character in field or table names. The double-quote (") should be what you're looking for.
Besides, I do believe that the Borland Database Engine is required in order to work against a Borland database such as Paradox. At least, that what I have always been told to, though I have never yet experienced such architecture, since I was using Delphi when working with Paradox.
As you founda (somewhat convoluted) solution...
Might be worth putting an ODBC trace on and seeing how Access is passing the field name that's causing the issue. It may just be an escape sequence that paradox accepts for the hash (#) or something similar. Just a thought.
I was able to reproduce the problem by creating a table (Table1) with a column that has number sign (col#). Like:
INSERT INTO `Table1.db` (`col#`) VALUES ('a')
Where I run this SQL I get this Error:
The INSERT INTO statement contains the following unknown field name: 'col#'. Make sure you have typed the name correctly, and try the operation again.
This seems to be a bug Microsoft JET provider. The only workaround is found is to insert the value into another column like
INSERT INTO `Table1.db` (`col1`) VALUES ('a')
And then update the col# column:
UPDATE `Table1.db` SET `col#` = col1
I found other problems with the JET provider. For example, you will get this wrong error if the table is does not have a primary key or password protected:
Operation must use an updateable query.

How to fetch lots of database table records by primary key?

Using the ADO.NET MySQL Connector, what is a good way to fetch lots of records (1000+) by primary key?
I have a table with just a few small columns, and a VARCHAR(128) primary key. Currently it has about 100k entries, but this will become more in the future.
In the beginning, I thought I would use the SQL IN statement:
SELECT * FROM `table` WHERE `id` IN ('key1', 'key2', [...], 'key1000')
But with this the query could be come very long, and also I would have to manually escape quote characters in the keys etc.
Now I use a MySQL MEMORY table (tempid INT, id VARCHAR(128)) to first upload all the keys with prepared INSERT statements. Then I make a join to select all the existing keys, after which I clean up the mess in the memory table.
Is there a better way to do this?
Note: Ok maybe its not the best idea to have a string as primary key, but the question would be the same if the VARCHAR column would be a normal index.
Temporary table: So far it seems the solution is to put the data into a temporary table, and then JOIN, which is basically what I currently do (see above).
I've dealt with a similar situation in a Payroll system where the user needed to generate reports based on a selection of employees (eg. employees X,Y,Z... or employees that work in certain offices). I've built a filter window with all the employees and all the attributes that could be considered as a filter criteria, and had that window save selected employee id's in a filter table from the database. I did this because:
Generating SELECT queries with dynamically generated IN filter is just ugly and highly unpractical.
I could join that table in all my queries that needed to use the filter window.
Might not be the best solution out there but served, and still serves me very well.
If your primary keys follow some pattern, you can select where key like 'abc%'.
If you want to get out 1000 at a time, in some kind of sequence, you may want to have another int column in your data table with a clustered index. This would do the same job as your current memory table - allow you to select by int range.
What is the nature of the primary key? It is anything meaningful?
If you're concerned about performance I definitely wouldn't recommend an 'IN' clause. It's much better try do an INNER JOIN if you can.
You can either first insert all the values into a temporary table and join to that or do a sub-select. Best is to actually profile the changes and figure out what works best for you.
Why can't you consider using a Table valued parameter to push the keys in the form of a DataTable and fetch the matching records back?
Or
Simply you write a private method that can concatenate all the key codes from a provided collection and return a single string and pass that string to the query.
I think it may solve your problem.

How do I get the C# Query component to recognise columns returned data from a temporary table in a sql stored procedure

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.

Categories

Resources