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

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).

Related

Inserting FK values in Entity Framework that already exist (identical entries) in one table without updating the primary key of another table

I recently asked a question related to this and found a solution, but realized I may have a bigger problem. If anyone can tell me if I'm able to do what I describe below without making changes to the database it would be greatly appreciated! Note: I'm new to Entity Framework.
I am trying to insert into this table (Agreement Settings) duplicate SettingsId values for a new agreement (associated with an agreementId that is illustrated in the table as a column).
However, a SettingsId is also stored in a table with these columns Algorithm Settings. The Id column represents a SettingsId and is the primary key of this table.
I only want to update the Agreement Settings table (the former table above) with these new duplicate SettingsId values and leave the latter table alone. That way I will have agreements that have duplicate SettingsId guids but only one unique representation of that guid in the Algorithm Settings table.
When I try to insert into the database using Entity Framework:
dataTransferAgreement = (await _dataTransferContext.Agreements
.AddAsync(dataTransferAgreement))
.Entity;
I get brand new guids for SettingsIds returned, although the object dataTransferAgreement has the duplicate guids as properties beforehand (they are replaced). I assume this is because Entity Framework sees these foreign keys in Agreement Settings table and their association to Algorithm Settings table (the primary key) and automatically updates the primary key and thus the associated foreign keys on its own.
I of course can't add the Algorithm Settings table properties to dataTransferAgreement, as that would cause a primary key conflict.
The question: is there any way to manually (or otherwise) insert these duplicate foreign key values into Agreement Settings table without touching the Algorithm Settings table in Entity Framework (code first)? Currently, the entity property that inserts the primary key Id for SettingsId is decorated with [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)], which is used in numerous other places in this project, so I assume I cannot change that.
Also, the entity property that associates this table in the code:
[ForeignKey(nameof(SettingsId))]
public AlgorithmSetting AlgorithmSetting { get; set; }
is not needed in my case (since I don't want to do anything with it), but I can't just remove it due to it being a domain model (again, I'm an Entity Framework newbie so if I'm wrong in any way please correct me).
In your agreements settings table, add a primary key "id", alongside the other two columns you already have. Entity Framework and relational databases aren't going to support the same primary key.
If you need to query the agreement table in the future, you can do so with any column values and just "ignore" the new primary key you added.
Happy to help further if needed.

Write in many to many relationship table with only primary key

I have two tables like this:
And between these tables there is a Junction table like this:
*appartiene_squadra*
field name (**primary key**)(*foreign key to first table*)
field name (**primary key**)(*foreign key to second table*)
Now, the problem is that the model recognize only the first two tables and I can't write data in appartiene_squadra. How I can write data here?
You're right in identifying that Entity Framework creates the junction table for you.
To enter data, you do not "add data to the junction table". What you do is add data to the navigational property, which will automatically be stored in the junction table by Entity Framework.
using(var db = new MyDataContext())
{
Installatori myInstallatori = db.GetExistingInstallatori(); //Assume this gives you an existing entity
Squadra mySquadra = db.GetExistingSquadra(); //Assume this gives you an existing entity
//You can do it this way
myInstallatori.squadra.Add(mySquadra);
//or this way
mySquadra.installatori.Add(myInstallatori);
//And then you save it to the database
db.SaveChanges();
}
I've shown an example of adding A to B, and B to A. Please note that you should only do one of these at the same time (at least when it is your intention to save to the database, rather than simply populating the entity in memory).
Also, to remove a row from the database:
mySquadra.installatori.Remove(myInstallatori);
db.SaveChanges();

Retrieve Values from database using Entityframework

I want to retrieve all rows which satisfying a condition. But when i tries only row count is correctly showing on debugging and the very first row value is repeatedly getting. following is my code
var data = (from jlist in entity.JobDetails
where jlist.JobID == QJobID
select jlist).ToList();
only first row value is showing in the var data. I have more than 1 items to be displayed
Repetitive identical objects are nearly always a tell-tale of primary key inaccuracies: the PK that EF knows about does not uniquely identify the actual records in the database. This frequently happens when views are mapped to EF models, because a view is just a stored query that maybe doesn't even bother about unique identification.
In your case you changed the single primary key to a composite key, without EF knowing it, or you only told EF that JobID was the primary key.
When EF materializes an entity object it creates an EntityKey for it that has a reference to the entity. These EntityKey have to be unique, otherwise the change tracker crashes. So when there are two entities, identified by { 1, 1 } and { 1, 2 }, while EF only looks at the 1, EF will use an existing entity key for the second entity. The weird part, I think, is that EF still decides to materialize a second instance matching this entity key. If it wouldn't you'd have seen only one JobDetails record which might have better directed your suspicions to the right spot.

Using DeleteAllOnSubmit when the table has no primary key

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();

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;
}
}

Categories

Resources