Adding row to relational table - linq to sql - c#

I have 3 primary Tables - Picture, Album and Collage. Collage and Album can have 1-many pictures. Pictures do not have to be in Album to be added to the Collage.
To define their relationship, I have AlbumPicture and CollagePicture tables.
My problem is when I try to add picture already uploaded to the Collage and hence to the CollagePicture table. It throws primry key violation error on PK_Picture since picture already exists.
CollagePictures.InsertOnSubmit(new CollagePicture {Collage = CollagePicture = existingPic});
I need to add one record in CollagePicture for existing picture and new Collage. Is there any way I can tell linq to not add picture if it already exists?
I am new to Linq and still learning.
EDIT:
sorry If I was not clear.
I assign PK to Picture as GUID when Pictures are uploaded. In CollagePicture I already have this pictureId with different collage
e.g.
CollagePictureId [PK]= 1
CollageId=1
PictureId = 1234567890123456
Now I want to add same Picture with different CollageId say,2. When I try to add anything to CollagePicture it tries to add to the Picture table as well. and that is when I get an exception. Hope this will clear things up.

I finally made it work..
Instead of this
CollagePictures.InsertOnSubmit(new CollagePicture {Collage = Collage, CollagePicture = existingPic});
It should be
CollagePictures.InsertOnSubmit(new CollagePicture {Collage = collage, CollagePicture.PictureId = existingPic.PictureId});
When you add an object to the relational table entity it adds the object in primary table as well. so just referencing Id makes sure that it does not do anything to the primary table.
It was easy and I should have tried that before..but Thanks for everyone's help though.

What primary key do you have on CollagePicture table? It's not really clear, what do you want to do when inserting new entry to CollagePicture. Do you mean that you add the existing picture to an existing collage? If so your primary key should be (PictureId, CollageId)

Without a detailed view of your data model, it's really hard to take a guess.
If you correctly configured your relations and LINQ to SQL, you could do something like the following:
collage.Add(Picture);
That way LINQ to SQL would add the right rows to the tables.
To check if the picure already exists in the Collage, you would do something like this.
collage.Pictures.Where(p => p.ID == pictureID).Count() > 0

If the PK of existingPic is 0 (assuming type int) then it is new, else it already exists.
if(existingPic.pkColumnId == 0)
CollagePictures.InsertOnSubmit(existingPic);

Related

Editing duplicate values in a database

I have a DataGrid View pulling some items from my database. What I want to achieve is to be able to edit the pack size or the bar_code fields. I am aware on how to update values in a database but how would I go about doing it if the data is the same? Meaning in many instances a bar code would have multiple pack sizes that is related to the one bar code number. Let's say I have the below screenshot. A data entry error was made and the bar_code and PackSize columns are the exact same. I want to change the first bar code to "1234." How would I achieve this? I can't say update barcode to 'textBox1.Text' where bar_code = '771313166386' because it would then change both data. How do I go about only focusing on one row of data at a time?
You can try using this query to update only the first row:
UPDATE TOP (1) my_table
SET bar_code = '1234'
WHERE bar_code = '771313166386'
You should have an auto-increment id column or a Primary key in your table.
I'd suggest you handle the logic of data duplicate manipulation at the backend rather than pulling them inside the grid and handle it there.
The following query will help you retrieve the duplicate records based on the mentioned columns. You can change it to UPDATE or DELETE as per your requirement.
-- Using cte and ranking function
;With CTE
As
(
Select
Product,
Description,
BarCode,
PackSize
Row_Number() Over(Partition By Product, BarCode, PackSize Order By Product) As RowNum
From YourTable
)
Select * From CTE
-- Where RowNum > 1;
Hope this is helpful :)
This might not help you directly in your answer. But, it is important to mention that your table design is incorrect. You should ensure the data integrity by creating a primary key in your table.
So when you need to update a product you have only one row to update.
Then you can add more tables and use foreign key references between them.
You need to uniquely represent the products. As per your sample data, I guess that there isn't any primary key on your table.
What you can do is either specify a unique constraint on columns to ensure that this type of data entry cannot be done.
If you cannot come up with list of columns to uniquely identify the rows, you can use surrogate keys by specifying Identity column and then while updating, always put a constraint where thisIdentityColumn=value
A data entry error was made and the bar_code and PackSize columns are
the exact same
I think this is the key. Essentially, the exact duplicates are unintentional, and the rows should be unique. Further it looks like bar_code + pack_size is your primary key (subject to data being entered correctly).
So, when you do an update, simply update the first row found that matches a bar_code and a pack_size. If it isn't unique, then the update should ensure that you are one step closer to unique rows in the database.
If you need a non-verbal answer, let me know.

INSERT INTO or UPDATE in case of condition

I am facing a problem at the moment, and I would like a quick solution for this.
I already found another answers about this issue but none had helped, I had read about INSERT INTO and INSERT ON DUPLICATE KEY UPDATE, but I think it doesn't really help me.
So the thing is, I have some Migrations enabled that Add new columns to existing tables, the thing is that the existing records on table prior to Migration get records with empty values even on existing columns (because I am changing the order of the columns on the new table migrated)
I am doing a SP that it's purpose is to fill the new Table migrated, according to Inserts or Updates.
I want to insert new records always except in the case that I found an existing record on the table with empty columns (column Id - primary key - is filled)
The "pseudo code" (mixing sql tables knowledge and c# syntax) would be something like this:
int i = 0;
foreach(Record item in importing_data_table)
{
if(i < tableMigrated.Length && tableMigrated[i].Column IS NULL)
{
UPDATE tableMigrated[i] SET Column = item.Column
}
else
{
INSERT INTO item
}
i++;
}
NOTE: Deleting all the rows from the tableMigrated before inserting is not possible, because there are foreign keys to that table. I got the following error trying that approach:
- The DELETE statement conflicted with the REFERENCE constraint "FK_blabla.Testing_testingTest.tableMigrated_Id".
NOTE2: Maybe my only option is using Cursors?
Thank you so much for your help in advance!
In your Stored Procedure, use the Merge Statement. Merge provides the functionality to INSERT based on your insert condition, otherwise UPDATE. Here is an example
MERGE dbo.FactBuyingHabits AS Target
USING (SELECT CustomerID, ProductID, PurchaseDate FROM dbo.Purchases) AS Source
ON (Target.ProductID = Source.ProductID AND Target.CustomerID = Source.CustomerID)
WHEN MATCHED THEN
UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate
WHEN NOT MATCHED BY TARGET THEN
INSERT (CustomerID, ProductID, LastPurchaseDate)
VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)
Take a look at Technet - Inserting, Updating, and Deleting Data by Using MERGE

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

EF Frustration mapping a view to an object

I have a table that hold records of part numbers for a specific project like so:
create table ProjectParts
(
PartNumber varchar(20) not null,
ProjectID int not null,
Description varchar(max) not null,
primary key nonclustered (PartNumber, ProjectID)
);
I have a view that will collect inventory information from multiple places, but for now I basically have a skeleton:
create view ProjectQuantities as
select distinct
pp.PartNumber,
pp.ProjectID,
0 as QtyOnHand,
0 as QtyOnOrder,
0 as QtyCommitted
from
ProjectParts pp;
So far, so good. I go into EF designer in Visual Studio (I already had an object model using the ProjectParts table) and update the model from the database. I select the ProjectQuantities view, click ok.
EF tries to divine the key on the table as a combination of all columns, but I fix that so the key for the object is the PartNumber and ProjectID columns. I check to make sure this validates, and it does.
Next, I add an 1:1 association between the ProjectPart object and the ProjectQuantity object in the EF UI and click OK. Now, when I try validating, I get the message Error 11008: Association 'ProjectQuantityProjectPart' is not mapped. Seriously? It can't figure this out? Alright, I select the link, go to the Mapping Details, and add the ProjectParts table. It adds both tables and meshes up the key relationships. My job is done. I run the validation.
No luck for me. Now I get the error Error 3021: Problem in mapping fragments starting at line (line number): Each of the following columnes in table ProjectParts is mapped to multiple conceptual side properties. The the message lists the ProjectID and the PartNumber columns and their references to the association I just created.
Well duh! Of course there are multiple references! it's a 1:1 compound key, it has to have multiple references!
This is stopping me from getting stuff done. Does anyone know a simple way to fix this so I can collect Quantity information when I'm collecting data about a project and its parts?
Thanks!
You may find this article useful http://blogs.u2u.be/diederik/post/2011/01/31/Building-an-Entity-Framework-40-model-on-views-practical-tips.aspx

linq to sql linking objects by multiple ID fields

Im working on a project at work which is pretty much a commissioning manager and i cant seem to figure out how to link the Items table properly in linq to sql.
I have a package detail table that has (among other things)
DepartmentID, CategoryID, ItemID
And the Items table (is actually a database view as its from a different database and is read only in this app) also have these 3 fields but when i add an association with these 3 fields it doesnt add that as a property object ot the PackageDetail class
am i doing something wrong with the association? all the single ones im doing work fine...
I don't believe that Linq-to-SQL can properly model an association with a composite key:
Is it beneficial to use multicolumn (composite) primary keys when using Linq to SQL?
However, you can still load objects with composite keys in a Linq-to-SQL query using an anonymous object as the (single) key:
http://msdn.microsoft.com/en-us/library/bb399391.aspx
have marked those ID fields as Primary keys? Make sure you assign the necessary columns as primary keys and this should work fine. Hope it helps
Ensure the keys are correctly setup with primary key and foreign key relationship. If that still doesn't work, could you consider adding a new key column, rather than relying on composite key?
Last option with LINQ to SQL is usually manually updating the DBML with an XML editor. A normal single key relationship appears as follows:
<Association Name="Schedule_Profile" Member="Schedule" ThisKey="ScheduleID" Type="Schedule" IsForeignKey="true" />
Suggest you try creating the element yourself, and try setting ThisKey to a csv list of columns. The OtherKey attribute may also be of interest.
It looks like you could just use ItemId and ignore the other 2 since that is the most specific qualifier - in other words, Department and Category are fully determined by itemId.
Did you mean a query like this.
var result = from table in dbContext.table1 join table2 in dbContext.table2 join new { table.DepartmentID, table.CategoryID, table.ItemID} equals new {table2.DepartmentID, table2.CategoryID, table2.ItemID}
select table;

Categories

Resources