Using DeleteAllOnSubmit when the table has no primary key - c#

I am trying to delete records from a DB which has no primary key. The following works:
using (myDataContext db = new myDataContext ())
{
db.ExecuteCommand("DELETE FROM myTable WHERE TradeDate = {0}", date);
}
(where date is an input to the function). But when I try convert it to LINQ
using (myDataContext db = new myDataContext ())
{
db.myTable.DeleteAllOnSubmit(db.myTable.Where(t => t.TradeDate.Date == date.Date));
db.SubmitChanges();
}
I get the following error because the table doesn't have a primary key:
Additional information: Can't perform Create, Update, or Delete operations on 'Table(myTable)' because it has no primary key.
I found the following old posts about this issue
DB:4.44:Dml Operations Using Linq Query For A Table Without Primary Key zm
Dml Operations using linq query for a table without primary key.
But I don't understand how to implement the fix they suggest (i.e. setting another key to IsPrimary).
Is there a way to do this using LINQ? Bear in mind that adding a PK to the actual SQL table is not an option (unless I just add a row counting identity column).

Without a primary key the two interfaces aren’t emitted: INotifyPropertyChanging and INotifyPropertyChanged and so LINQ to SQL doesn’t know that your record has changed. Do the following:
Open the LINQ Designer.
Open the properties window for the table you want to delete a record from.
Click on any of the columns in the entity you want to delete and you'll see a property labeled "Primary Key".
Change the value to true for column you want to use as a primary key.

Please, use the unique column as a Primary Key in the EF model.
Otherwise use DataContext.ExecuteCommand()

As others have pointed, you need to add a primary key to your table. And then execute the query.
Else you can try to delete the row manually like this:
var query = myTable.AsEnumerable().Where(r => r.Field<Date>("TradeDate") == date.Date);
foreach(var row in query.ToList())
row.Delete();

Related

EF5: Conflict with the FOREIGN KEY constraint

I'm new to using entity framework. I'm using EF5 to insert new data.
I get the dreaded error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_POSTransactionsKitMemberTaxRaw_POSTransactionsKitMemberSaleReturnRaw_KitMemberSaleReturnRowId".
I understand that to mean I don't have a row in [POSTransactionsKitMemberSaleReturnRaw]
with a primary key that matches the insert for table [POSTransactionsKitMemberTaxRaw].
I wanted EF to generate the primary keys for me and expected the missing row to have been generated automatically. Here's the code that's failing:
foreach (POSTransactionsKitMemberSaleReturnRaw posTransactionsKitMemberSaleReturnRaw in posTransactionsKitMemberRaw.POSTransactionsKitMemberSaleReturnRaws)
{
++KitMemberSaleReturnRowId;
// set temporary keys
posTransactionsKitMemberSaleReturnRaw.KitMemberSaleReturnRowId = KitMemberSaleReturnRowId;
posTransactionsKitMemberSaleReturnRaw.KitMemberRowId = KitMemberRowId;
repository.AddPOSTransactionsKitMemberSaleReturnRaw(posTransactionsKitMemberSaleReturnRaw);
foreach (POSTransactionsKitMemberTaxRaw posTransactionsKitMemberTaxRaw in posTransactionsKitMemberSaleReturnRaw.POSTransactionsKitMemberTaxRaws)
{
// set temporary keys
posTransactionsKitMemberTaxRaw.KitMemberTaxRowId = ++KitMemberTaxRowId;
posTransactionsKitMemberTaxRaw.KitMemberSaleReturnRowId = KitMemberSaleReturnRowId;
posTransactionsKitMemberTaxRaw.KitMemberKitMemberSaleReturnRowId = null;
repository.AddPOSTransactionsKitMemberTaxRaw(posTransactionsKitMemberTaxRaw);
}
}
I've validated that there are temporary primary key values in the POCO objects at run time. A sql trace of the activity shows the attempted insert value was a generated value (1439630) not the temporary value I set it to.
I've set the Auto detect changes flag off:
_context.Configuration.AutoDetectChangesEnabled = false;
The intent was to improve performance. Since this is a pure insert
there should be no way the database rows will change while I am trying to write them.
Any suggestions?

C# sql copy rows with 3 primary keys

I am working on an existing table where as I can see there are 3(!) primary keys:
I want to copy the existing rows, alter the ctid column and then copy them again to the end of the table. I try that and I am getting the error:
Cannot add an entity with a key that is already in use.
Probably because I am copying the rows and adding them with the same primary keys. How I can solve this? Is it possible to solve it without modifying the db schema (I am thinking of adding ctid as primary key also)?
Code
var testsDefault = (from i in dc.TestUnits
where i.ctid == null
select i).ToList();
List<DAL.TestUnit> TestList = new List<DAL.TestUnit>();
foreach (var test in testsDefault)
{
DAL.TestUnit newTest = new DAL.TestUnit();
newTest.TestID = test.TestID;
newTest.PatientType = test.PatientType;
newTest.Unit = test.Unit;
newTest.ctid = "105";
TestList.Add(newTest);
}
dc.TestUnits.InsertAllOnSubmit(TestList);
dc.SubmitChanges();
You need to add ctid to your composite primary key.
ALTER TABLE TestUnits
DROP CONSTRAINT PK_WhateverYourCompositeIndexNameIs
ALTER TABLE TestUnits
ADD CONSTRAINT PK_WhateverYourCompositeIndexNameIs PRIMARY KEY (TestID, PatientType, Unit, ctid)
See: How can I alter a primary key constraint using SQL syntax?
No,it is not possible what you are trying to do without modifying the db schema. Since you are using three PK and Primary key can not be duplicate as you are trying to do. The solution to your problem is make all the row's columns unique and then add the another row but make sure all tuples must have unique entries.
The another solution to your problem is already given by Rafalon

Implement an efficent mechanism to check whether a record is referenced in other tables before delete

I am developing an web app using asp.net. I am making this app for compatable for both SQL and MYSQL DB.
So my concern is think that I have a set of records in a table. This table's records are referenced by other tables. So if a user try to delete a record from this table I have to check whether this record is referenced by other tables or not. If not then user can delete the record. I am using using foreign keys for many tables but others not.
So I want this scenario for every tables. So method that coming to my mind is before delete a record I have to run some select queries against those tables to check whether if records available. So is this the only approach.? Seems to its headache. you know if table is referenced by lot of tables. Can I use a flag or some thing?
Is there any better way to do this?
I think this might help you ::
SELECT
table_name, column_name
FROM
information_schema.key_column_usage
WHERE
referenced_table_name = '<table>'
and referenced_column_name = '<primary key column>'
Please check this link too:
MySQL: How to I find all tables that have foreign keys that reference particular table.column AND have values for those foreign keys?
I think it is a little overkill and not performance optimized to be selecting tables and references to check before each delete. You will be making unnecessary database calls.
Since you tag'd ASP.Net are you using ADO ? If so, or similar.
Why not make the normal delete call inside a try block and in the catch handle error message received from database something like:
try
{
}
catch(SqlExcpetion sqlEx)
{
if(sqlEx.Message.ToLower().Contains("foreign"))
{
return "your user friendly error message";
}
}
In case you are using foreign keys to constraint the references, you can act in the following order:
consider you are using database test and are trying to delete a row from emp table
1) list all the tables with their column names, that reference any column in the table we are going to remove a row from (emp in this case)
select
table_name,column_name,referenced_column_name
from
information_schema.KEY_COLUMN_USAGE
where
REFERENCED_TABLE_NAME = 'emp' and REFERENCED_table_schema = 'test';
2) for each row of the result try looking up the value of referenced_column_name from the emp row that is being removed in the corresponding table_name.column_name

Table name as part of primary key

I have an audit trailing system in my project from http://doddleaudit.codeplex.com/.
As you can see on this image it records the EntityTable - which is the table name, and the EntityTableKey - which is the primary key
I would like to associate the audit records with the tables it had recorder, then query the result in linq to sql. But the problem is if the audit table has record for orders and record for products it will never know just by the primary key, where does the record belong, thus i need to use the table name as part of the key.
So the question is: Is it possible to create a relation that will have a composite primary key that contains the table name in it?
AuditRecord to Orders
AuditRecord to Products
You could do it, but I would recommend a bit different approach.
Don't use char/varchars/nvarchar in your PK/FK, it bloats the index. I would rather create another table that will hold TableId/TableName pairs of all your tables (you can use sys.tables.object_id for your id if you wish) and have a FK in AuditRecords to it. Then establish composite key between AuditRecords and AuditRecordFields (Id, TableId).
Another thing:
EntityTable and AssociationTable should be of sysname type
AuditDate can be of type Date (available from SQL Server 2008)
EDIT:
If you like to access audit records from each object, you can create a base class for your audited objects and implement following method (beware, it's untested):
public IQueryable<AuditRecord> AuditRecords
{
get
{
MyContext ctx = new MyContext();
var ars = from ar in ctx.AuditRecords
where ar.EntityTable.Equals(this.GetType().Name)
select ar;
return ars;
}
}

Creating and Inserting new entity from Existing One in Linq To Sql

I have 2 tables; PriceList and PriceListDetail with one to many realitonship. After inserting a new PriceList and I need to copy PriceListDetail's of an existing PriceList.
var pricedetails= db.PriceListDetails.Where(p => p.PriceList Id == SomeExistingPriceListID);
All I need is to change priceListID of pricedetails above and Insert them to PriceListDetail table. When I modify priceListId of pricedetails and try to insert them I get 'cannot insert entities that already exists'.
Obvious solution is to create new entities and copy values one by one from pricedetails then insert.
Is there a way to avoid one by one copying? Maybe create duplicate rows then modify duplicated ones?
Entity frameworks uses another key than your primary key, and it is called an entity key.
So having your PriceListDetails, all you have to do is to change the primary key ID and set the entity key to NULL (NULL means a new row).

Categories

Resources