A little background information: I have a table called table_a, which has 12 columns. I want to insert or update rows with values for 6 of these columns, while I don't wanna lose the data in the other 6 columns. And I wanna do this with a parameterized query in C#.
field1 is Unique.
> SELECT * FROM table_a;
+----+--------+--------+---+---------+---------+
| Id | field1*| field2 |...|field11 | field12 |
+----+--------+--------+---+---------+---------+
| 1 | AA | BB |...| KK | LL |
| 2 | AA | BB |...| KK | LL |
| 3 | AA | BB |...| KK | LL |
| 4 | AA | BB |...| KK | LL |
+----+--------+--------+---+---------+---------+
The Problem is, my first thought was to use REPLACE INTO, unfortunately this will delete the 6 not touched values:
> REPLACE INTO table_a (field1, ..., field6) VALUES ('AA', ...);
> REPLACE INTO table_a (field1, ..., field6) VALUES ('AB', ...);
+----+--------+--------+---+---------+---------+
| Id | field1*| field2 |...| field11 | field12 |
+----+--------+--------+---+---------+---------+
| 1 | AA | BB |...| NULL | NULL |
| 2 | AB | BB |...| NULL | NULL |
| 3 | AC | BB |...| KK | LL |
| 4 | AD | BB |...| KK | LL |
+----+--------+--------+---+---------+---------+
My second thought was to use INSERT INTO ... ON DUPLICATE KEY UPDATE, but then I'd have to bind the parameters a second time, the first time in the INSERT part and the second time in the UPDATE part, like this:
INSERT INTO table_a (field1, ..., field6)
VALUES(?, ..., ?)
ON DUPLICATE KEY UPDATE
field1 = ?, ..., field6 = ?;
That would preserve my data, but I have to bind the parameters twice.
The third option would be to create another two queries and use the SELECT and INSERT INTO/UPDATE pattern.
So, my question is, how do I do this the smart way?
Your second option sounds like a winner for single row updates.
Your third option is good if you insert/update many rows at once (as it will not matter much that you have two queries then - providing each does only what it is supposed to do).
UPDATE:
Digging through documentation one finds that you can bind once if you wish - you can refer to the originally bound values with VALUES()
UPDATE2:
Well, actually you can not get to the bound values with VALUES(column), so instead two suggestions that actually might help:
did you check about using named parameters (then you would not need to bound them twice)?
did you consider stored procedures?
I think you've listed all the available options, along with the pros/cons of each. As for the third option, you would probably want to wrap your two queries in a transaction to ensure that the operation remains atomic.
Hi let's say you want to modify field2 to field6.
why wouldn't you do:
replace into table_a select field1,new_value2,...,new_value6,field7,...,field12 from table_a where field1=filter_field1;
You put the new values and you get the others value by querying the table you're updating.
Related
I have this ef query that give me the following result
IQueryable<A>
| Id | count |
| 1 | 5 |
| 2 | 6 |
IQueryable<B>
| Id | count |
| 1 | 1 |
| 2 | 2 |
| 3 | 9 |
When I do
IQueryable<Something> C = A.union(B)
Result that I got is this
| Id | count |
| 1 | 5 |
| 2 | 6 |
| 1 | 1 |
| 2 | 2 |
| 3 | 9 |
Whish is logical.
What I want is a UnionBy(Id)
IQueryable<Something> C = A.unionBy(B,c=>c.Id)
and this work perfectly in my case
| Id | count |
| 1 | 5 | -- FROM A
| 2 | 6 | -- FROM A
| 3 | 9 | -- FROM B
If the Query A or B are already executed by that I mean a ToList() was made it work perfectly and I have no problem in anyway.
But in my case, both queries are not executed and thus using this function result in.
System.InvalidOperationException query could not be translated.
the alternative is to use a GroupBy however I have no idea how to replacte UnionBy behavior with the GroupBy
FYI: the query works perfectly using the IQueryable.Union
and it's mandatory in my case that the request stay in IQueryable and not executed until later
UPDATE
⚠️ The solution that I'm looking for must stay in IQueryable without a toList() execution
"query could not be translated" usually means that EF doesn't support a certain LINQ or language construct as it can't translate it into SQL. One way to make this work is to force the evaluation of the expression client-side by adding e.g. ToList() or likes on the query parts before executing the UnionBy:
IQueryable<Something> C = A.ToList().UnionBy(B.ToList(),c=>c.Id);
The solution is simple you filtre A From B using the following
IQueryable<Something> C = A.Union(B.where(b=> A.All(a=>a.Id != b.Id))
Let's assume that I'm having two tables: PropertyTypes and Properties
PropertyTypes
ID | Name
1 | Color
2 | Country
3 | Size
Properties
ID | ID PropertyTypes | Name
1 | 1 | Red
2 | 1 | Blue
3 | 1 | Green
4 | 2 | China
5 | 2 | Macau
6 | 3 | S
7 | 3 | L
For example, if I choose properties 1,2,4 5 above, if there are 2 distinct PropertyTypes, the list I want looks like (2x2=4):
Red-China
Red-Macau
Green-China
Green-Macau
If I choose all properties, here are 3 distinct PropertyTypes, the list I want which looks like(3x2x2=12):
Red-China-S
Red-Macau-S
Blue-China-S
Blue-Macau-S
Green-China-S
Green-Macau-S
Red-China-L
Red-Macau-L
Blue-China-L
Blue-Macau-L
Green-China-L
Green-Macau-L
And so on, if we add more PropertyTypes and Properties in the future
I can't figure out how to do the loop to get those result for future extending without changing the code and avoid duplicating.
Please help me if you figured out something.
I have got a List with the following object
// Properties
long InstID
long SheetID
String[] Names
Double[] Values
The populated list contains the following items
InstID | SheetID | Names | Values |
-----------------------------------------------------------------
8 | 100 | 2,3,4,5 | 200, 300, 400, 500 |
9 | 100 | 2,3,4,5 | 2000,3000,4000,5000 |
8 | 101 | 2,3,4,5 | 201, 301, 401, 501 |
9 | 101 | 2,3,4,500 | 2001, 3001, 4001, 5001 |
I want to make use of this list and create a data structure with the following Columns and Rows
The columns Names
-----------------
SheetID
InstID_Name
Rows
-----
Instrument Values
Using the list above the output should look as below
SheetID |8_2 |8_3 |8_4 |8_5 |9_2 |9_3 |9_4 | 9_5 |
-------------------------------------------------------------------------
100 |200 |300 |400 |500 |2000 |3000 |4000 |5000 |
101 |201 |301 |401 |501 |2001 |3001 |4001 |5001 |
What I have tried
I have tried to create a datatable and try to loop through the list to create the columns and populate the rows. This seems very convoluted, I am hoping to get some ideas on how to implement this. If there is anything in .Net framework which will make this task easier.
Thanks in advance.
My data comes from IQueryable that looks like the following table when I return all of the DailyCollectionActivities.
CatType | CdDescr | CollTypeDescr | RollCasteDescr | TIFDescr | TADescr | Amount
--------------------------------------------------------------------------------
Cat 1 | Cd 1 | CollType 233 | Roll Caste 234 | TIF 2344 | TA 2343 | 344.35
Cat 1 | Cd 1 | CollType 222 | Roll Caste 235 | TIF 2345 | TA 2344 | 355.35
Cat 2 | Cd 2 | CollType 223 | Roll Caste 236 | TIF 2346 | TA 2345 | 664.44
Cat 3 | Cd 3 | CollType 255 | Roll Caste 236 | TIF 2347 | TA 2346 | 455.34
Cat 4 | Cd 4 | CollType 266 | Roll Caste 236 | TIF 2348 | TA 2347 | 455.44
I'm trying to find out if it's possible, using linq on the IQueryable<DailyCollectionActivity> data, to add two columns together and then group on that newly created column? For example I need to figure out how to add CatType to CdDescr (CatType + '-' + CdDescr) and then group by that newly created column and sum the Amounts. Finally, I then need to take the results of that query and bind it to a RadGrid.
To make things more interesting, the user is allowed to choose which columns get added together. I could wind up with a group by clause like (CatType + '-' CdDescr), (TIFDescr + '-' + TADescr).
Is this something that I can reasonably accomplish using Linq?
say its from categories
var result = from s in (
from p in categories
select new {
TypeDesr = p.CatType+"-"+ p.CdDesr,
CollTypeDescr = p.CollTypeDescr ,
RollCasteDescr = p.RollCasteDescr,
TIFDescr = p.TIFDescr,
TADescr = p.TADescr,
Amount = p.Amount
})
group s by s.TypeDesr into r
select r;
This should be a simple one, but I'm a beginner with C#.
Given a glossary list in the following format:
aptitude
ability, skill, gift, talent
aqueous
watery
arguably
maybe, perhaps, possibly, could be
How can I parse this, and insert into a database table in the format:
TABLE: Term_Glossary
================================================
Term_Name | Term_Definition |
================================================
aptitude | ability, skill, gift, talent |
------------------------------------------------
aqueous | watery |
------------------------------------------------
arguably | maybe, perhaps, possibly, could be|
================================================
Any help would be appreciated - thanks.
Update
I realize the database structure is simple/inefficient - but really, the point of my question is the code to parse the kind of text found in the first example, using C#. Thanks.
It may seem more complex at first, but you'll find it a lot easier in the long-term to think in terms of two tables:
===========================================
Term_ID | Term_Name |
===========================================
1 | aptitude |
2 | aqueous |
3 | arguably |
===========================================
===============================================
Definition_ID | Term_ID | Definition_Name |
===============================================
1 | 1 | ability |
2 | 1 | skill |
3 | 1 | gift |
4 | 1 | talent |
5 | 2 | watery |
6 | 3 | maybe |
7 | etc.etc.etc
Perhaps even think if you can normalise this further by having one table of words with IDs and a table of associations.
It looks to me like you would read the first line, save it to a variable, read the second line, save it to a second variable, then insert into the table where Term_Name = first variable, and Term_Definition = second variable.
So your logic would be like:
StreamReader SR;
string Term_Name;
string Term_Definition
SR = File.OpenText(filename);
Term_Name = SR.ReadLine();
while(Term_Name != null)
{
Term_Definition = SR.ReadLine();
// make your database call here to insert with these two variables. I don't know what DB you are using.
Term_Name = SR.ReadLine();
}
SR.Close();