I'm working on a WPF system which hooks onto an old legacy database using the Entity Framework. We hook onto a backup of the live data when debugging and an empty database to run tests against. I'm receiving the following error only when trying to delete from a backup of the live data.
This code:
License license = ReadLicense(id);
entities.DeleteObject(license);
entities.SaveChanges();
produces this SQL:
exec sp_executesql N'delete [dbo].[Product]
where ((([Group_ID] = #0) and ([Parent_ID] = #1)) and ([Prod_ID] = #2))',N'#0 nvarchar(32),#1 nvarchar(32),#2 nvarchar(32)',#0=N'someIdValue1',#1=N'someIdValue2',#2=N'someIdValue3'
which in turn produces this error:
Msg 208, Level 16, State 1, Procedure TrackDeletedProduct, Line 4.
Invalid object name 'DeletedRecords.dbo.Product_Deleted'.
If you change the generated SQL to a 'select' query it returns a row so, 'ReadLicense' is returning a valid entity. I can't really understand why this doesn't work, especially when it's only against live data. The 'License' entity is one of two inheriting from a base 'Product' entity.
Cheers.
From what I can see, it would appear as if your table Product has a trigger on it that will fire when you delete a row, and which calls that stored procedure TrackDeletedProduct.
That procedure will (just guessing here) try to copy the product entry to the Product_Deleted table in the DeletedRecords database, but fails on that - either that other database or the table don't seem to exist.
So I don't think this has really anything to do with ADO.NET Entity Framework or LINQ-to-Entities, but a lot with SQL Server - check your backend database configuration!
Marc
Related
I am trying to run this query via Npgsql, this query work well when i run it directly on the server because i get: Query returned successfully with no result in 15 ms.However, when i use Npgsql i get: 42P01: relation "sometable" does not exist
I know that the error is is in the INSERT statement, am i missing something ?
connection string: Host=192.168.137.47;Port=5432;UserId=postgres;Password=test;Database=pg_database;
var m_createdb_cmd = new NpgsqlCommand();
m_createdb_cmd.Connection = _connPg;
m_createdb_cmd.CommandText = psSQL;
_connPg.Open();
m_createdb_cmd.ExecuteNonQuery();
_connPg.Close();
The query
BEGIN;
CREATE TABLE "sometable" (
"test" varchar(254));
INSERT INTO "sometable" ("test") VALUES ('Hello World');
COMMIT;
The Log
2015-10-01 07:08:46 EDT ERROR: relation "sometable" does not exist at character 13
2015-10-01 07:08:46 EDT STATEMENT: INSERT INTO "sometable" ("test") VALUES ('Hello World')
p.s.:i've also looked at PostgreSQL ERROR: 42P01: relation "[Table]" does not exist does not help
This is due to a known limitation introduced in Npgsql 3.x - when sending multiple SQL statements in one command, later statements can no longer depend on entities created in earlier statements. For example, you can't create a table and then insert into it in the same command. The workaround is to simply split the table creation and the insert into two commands (note that this has nothing to do with transactions).
The issue tracking this is https://github.com/npgsql/npgsql/issues/641.
Create the table. Commit that Transaction.
Then in a separate transaction, insert the data.
I had similar problem with running the DB on docker, locally it was running fine.
The solution was to add [Table("MissingTableName")] above the class.
Interfacing to SQL Server 2008R2:
I have a linq expression:
IQueryable<xxx> xxxResult =
(from t in _context.xxxx.AsNoTracking().Include("yyy")
where t.zzz >= lowNumber
&& t.zzz <= highNumber
&& t.qqq == someValue
select t);
(It probably doesn't matter on the exact query, but it's there in case it does.)
Linq generated SQL that the SQL Server generated a terrible plan, and, since I can't add index/join hints, I created a stored procedure that wrapped the SQL that the above Linq expression generated.
I know I should be able to access the stored procedure through Entity Framework, but I'm using a previous project that used a very light code-first implementation (no .edmx file, for instance) and I'm kinda new to the whole EF thing and didn't know how to tie the new procedure into EF. I know it can be done, but I am trying to call the procedure directly.
I worked this out:
IQueryable<xxx> xxxResult =
_context.xxxx.SqlQuery("GetData #p0, #p1, #p2", someValue, lowNumber, highNumber)
.AsNoTracking().AsQueryable();
This seems to work, except for one problem. When iterating over the linq queryable, everything works swimmingly. But, when I use the stored procedure, I get duplicate records.
For instance, if I have an xxx record that includes 3 yyy records in a collection, I get a single xxx record from the linq expression and it, as expected, includes 3 yyy records in the internal collection.
The stored procedure, for the same dataset, iterating over the queryable returns three xxx records, EACH of which contain the same 3 yyy records.
Again, the stored procedure executes the exact same SQL that the linq expression generated.
Why is that? Any ideas?
(Again, new to EF, so please forgive errors in terminology.)
I believe that EF is seeing your results as duplicate based on the primary key you have defined. In EF5, this would be defined using the "Entity Key" property on the fields which uniquely define the entity (a multi-part primary key would have this set on multiple fields).
If your procedure returns a record that matches one that it already returned (based soley on the primary key fields) then it will return a reference to the previous record.
Your LINQ expression uses .AsNoTracking which should prevent this caching behavior.
I'm guessing that the .AsNoTracking() using the stored proc occurs after it has been cached and doesn't have the effect you are looking for.
Make sure that you have your primary keys set properly on your model.
Here's an article that describes the behavior with a view:
http://jepsonsblog.blogspot.in/2011/11/enitity-framework-duplicate-rows-in.html which should be similar to what you are seeing with the stored procedure.
It looks like in Code First, you would use the [Key] annotation to specify your unique keys: http://msdn.microsoft.com/en-us/data/jj591583.aspx
My EF Remove fails with the above statement. The table (Product) has a single primary key (ProductID). Running SQL Trace produced the following SQL that causes the failure:
exec sp_executesql N'DELETE [dbo].[Product] WHERE ([ProductID] = #0)',N'#0 int',#0=620895
Full error statement:
Msg 121, Level 15, State 1, Procedure t_del_Product, Line 8 The select
list for the INSERT statement contains more items than the insert
list. The number of SELECT values must match the number of INSERT
columns.
Other similar Removes work just fine. My EDMX is fully updated against the DataSource (SQL Server 2012)
Any ideas? Anyone? Anyone?
Thanks!
UPDATE: I should have tried this earlier, but I get the same error even with a simple:
DELETE FROM Product Where ProductID = 620895
So, it is not EF.
As mentioned in my comment:
It looks like the sp is being called (possibly) when a delete occurs on dbo.Product and is producing your error. Just look on the table and see if there are triggers defined on it.
If indeed there is a trigger on the table calling this SP, then this is likely your issue and you should look into fixing the SP.
I'm running MSSQL 2012 with the FTS engine enabled. I have the following sproc which performs full-text searching on a varchar column:
CREATE PROCEDURE [PROE].[SP_SearchLabOrdersByPatientNameAndDateRange]
#searchString varchar(160)
, #dtFrom datetime
, #dtTo datetime
AS
SET NOCOUNT ON
SELECT ord.Id, ord.FullName, ord.SomeOtherColumns
FROM
PROE.PatientLabOrders ord
WHERE
FREETEXT(ord.FullName, #searchString)
AND ord.OrderDateTime BETWEEN #dtFrom AND #dtTo
When I import the above stored procedure, the EDM model designer doesn't show any DTO column information. Instead, the model browser displays the following message:
The Selected Stored Procedure or Function returns no columns
Image is:
I have a few variations of this sproc which perform regular (not FTS) searching on other columns - all of those sprocs are imported properly by EF 5. Only the above sproc is using full-text searching. I've run the above stored procedure in SQL server manager and it's returning rows as expected. Yet the EF5 designer still can't detect columns returned by the sproc.
What am I doing wrong?
its because you need to use the return keyword and return the column you are looking for i have no experience of doing this so im not going to post a query of google and hope it work but i do no this is your problem just google return column.
I'm having trouble trying to use the 'Auto-Sync' feature of DBML with SQLite. I have a class in my data model that contains a primary key (id). This key is defined as "INTEGER PRIMARY KEY", which SQLite maps to the rowid of the row. To support this, I have set "Auto Generated Value" to 'True' and "Auto-Sync" to 'OnInsert'.
The problem is, when I commit a new entry to the database, the SELECT string used by the LINQ to SQL classes is not supported by SQLite:
SELECT CONVERT(BigInt,SCOPE_IDENTITY()) AS [value]
Instead, SQLite has the last_insert_rowid() function, which I cannot seem to point to.
Does anyone know how to remedy this? Possibly by changing the statement used to select the last row ID or some other trick I'm missing?
EDIT There appears to be some traffic on the provider's website, but no resolutions.
EDIT Since I seem to have confused the question, here's how I've set up my application. Hopefully it helps shed some light on my thought process, and maybe an underlying issue.
Add new "LINQ to SQL Classes" file to my solution
Model my database in the designer, named DataModel
Open a database using a System.Data.SQLite.SQLiteConnection
Initialize the DataModel instance using this connection
You are adding a "Linq-to-SQL" data model to your project, but you're using it against SQLite - that'll never work of course! Linq-to-SQL only ever supports SQL Server (always has, always will), and thus its SQL statements that it generates are SQL Server T-SQL Statements - nothing else.
If you want to use the Entity Framework with SQLite, you need to use "ADO.NET Entity Data Model" (file with the .EDMX extension) as your data model.
Only that will support third-party database drivers like SQLite and others!
Devart implementation of LINQ to SQLite does not contain this problem. The autoincrememnt column is treated correctly.
I ran into the same issue and found the following workaround - use the SQLiteConnection.Changed event to intercept the query and fix it up:
SQLiteConnection.Changed += (obj, eventArgs) => {
var cmd = eventArgs.Command;
if (eventArgs.EventType == SQLiteConnectionEventType.NewDataReader && cmd != null)
{
cmd.CommandText = cmd.CommandText.Replace( #"SELECT CONVERT(Int,SCOPE_IDENTITY()) AS [value]"
, #"; SELECT last_insert_rowid() AS value");
}
};