Converting Sql query (update table set ....) to linq ( var m = ...) - sql

I am trying to write a linq query in my Database.cs file. I find it difficult. Is there any tool to convert sql to linq? I tried linqer but it is no good. Or could you help me in writing the following query in linq.
update table
set field1='R',
field2='" + DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss") + "',
field3 = '" + util.CleanStringInput(value1) + "'
where field1 = 'P'
and field3 = '" + value2 + "'
and field4 = (select max(field5)
from table2
where field6='" + value2 + "')

The easiest way would be to fetch the entities, set the properties and then save changes:
var maxFromTable2 = context.YourTables2.
Where(t2 => t2.field6 == value2).
Max(t2 => t2.field5);
var entitiesToUpdate = context.YourTables.
Where(t => t.field1 == "P" &&
t.field3 == value2 &&
t.field4 == maxFromTable2).
ToList();
foreach (var entityToUpdate in entitiesToUpdate)
{
entityToUpdate.field1 = "R";
entityToUpdate.field2 = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss");
}
context.SaveChanges();
NOTE: It is not clear from your question what table you are updating, so I assume by default that it is a table different from table2. It could help if you indicate whether you are using LINQ to SQL or Entity Framework (LINQ to Entitites). The current syntax is for EF.

LINQ to SQL/EF are intended to hydrate objects and operate on those, saving the changes. It is not intended as a replacement for batch operations. If you use EF/LINQ to SQL in this case, you will be issuing n+1 requests to the database: 1 to select the records you are going to change and a separate request for each row (object) you are updating. With a small data set, this may be managable, but if you have any kind of volume, keeping this in a stored proc using a single Update statement may be a better option.

Related

SQL check if record exists

So I spent some time to research what the best way was to check if a record exist was. Ended up with this.
var checkExistance = "SELECT TOP 1 exerVariName FROM exerciseVariants WHERE exerVariName = '" + exerVariName + "'";
However I failed many times to make this work while using it on my page!
var exerVariName = Request.Form["exerVariName"];
var checkExistance = "SELECT TOP 1 exerVariName FROM exerciseVariants WHERE exerVariName = '" + exerVariName + "'";
if (IsPost && Validation.IsValid()) {
if (ModelState.IsValid) {
foreach (var c in db.Query(checkExistance)) {
if (c.exerVariName != exerVariName) {
var insertData = "INSERT INTO exerciseVariants (exerVariName, exerVariNameID) " +
"VALUES (#0, #1)";
db.Execute(insertData, exerVariName, exerciseID);
Response.Redirect("~/insertexervariname");
}
}
}
}
So the variable I put into the SQL line is a request form thing so its a user input that I want to check if it exists in the database, if it already exists I dont want it to be posted. And the above is what i tried with the foreach in the if ispost.
How would one go about to achieve this? (c# razor/cshtml)
Your code has race conditions.
The best way to do what you want is to have the database enforce the constraint, using a unique index/constraint:
create unique index unq_exerciseVariants_exerVariName on exerciseVariants(exerVariName);
If you want to avoid the error on updates, then you can check as you update as well:
INSERT INTO exerciseVariants (exerVariName, exerVariNameID)
SELECT exerVariName, exerVariNameID
FROM (SELECT #0 as exerVariName, #1 as exerVariNameID
) x
WHERE NOT EXISTS (SELECT 1
FROM exerciseVariants
WHERE ev.exerVariName = x.exerVariName
);
Note that this check may not be sufficient due to race conditions, if two different threads attempt to insert the same name at the same time. That is why it is best to have the database enforce the uniqueness.
I am no C# person by any means, but I do see one logical problem with your current code. Currently your EXISTS and INSERT queries are being run separately, separated by several lines of .NET code and perhaps many more actual machine instructions. The net (no pun intended) result of this is that you might end up inserting when the existence check appears true but is no longer true. To avoid this, the existence check should appear in the WHERE clause of the INSERT. Something like this should work:
INSERT INTO exerciseVariants (exerVariName, exerVariNameID)
VALUES (#0, #1)
WHERE EXISTS
(
SELECT * exerVariName
FROM exerciseVariants
WHERE exerVariName = '" + exerVariName + "'";
)
Now the INSERT should happen atomically, meaning your check and the actual insert will all be done at the same time, regardless of what other threads might be doing.

Query to retrieve all row data for supplied column name

I am using Eclipse and Oracle SQL Developer. My connections are all set up. I am trying to query my database in SQL Developer by passing in a column name as a variable.
For example, I just want to use something similar to this statement:
select * from CUSTOMERS;
but allow CUSTOMERS to be a variable where I can pass in any table name.
Currently this pulls all column names from given column name and connection:
final String query = "select column_name from all_tab_columns"
+" where owner = ?"
+" and table_name = ?";
try {
headers = DAO.useJNDI(jndi)
.setSQL(query)
.input(1, host)
.input(2, tableName)
.list(String.class);
I want to do the same thing but with rows. Does anyone know how to do this? This is what I am thinking about so far:
final String sql = "select *"
+ " from table_name"
+ " where owner = ? and table_name = ?";
try {
logger.debug(tableName+sourceJNDI);
sourceList = DAO.useJNDI(sourceJNDI)
.setSQL(sql)
.input(1, host)
.input(2, tableName)
.list(DatabaseCompareDto.class);
The main focus is the SQL statements. I know everything else works.
If I'm reading your question correctly, I think what you want is to replace the first table_name in your SQL with ?, then add an additional .input( 1, tableName) :
final String sql = "select *"
+ " from ?"
+ " where owner = ? and table_name = ?";
try {
logger.debug(tableName+sourceJNDI);
sourceList = DAO.useJNDI(sourceJNDI)
.setSQL(sql)
.input(1, tableName)
.input(2, host)
.input(3, tableName)
.list(DatabaseCompareDto.class);
You can't pass the table name as a parameter. Instead of wasting your energy on such an alleged generic solution, use or create a small templating engine which allows you to replace the table name in your query before sending it to the database.

Order of JSON returned by ORMLite?

I'm new to web services and trying to query some tables using ORMLite, it doesn't support join statements so I'm using a raw query. I was wondering if there is a way to specify how the JSON is returned. What I have right now is:
Dao<CodesModel,String> CodesDao = DaoManager.createDao(connectionSource, CodesModel.class);
GenericRawResults<String[]> rawResults =
CodesDao.queryRaw(
"select r.CodeA, s.SubCodeA, r.CodeB, s.SubCodeB " +
"from CodesTable r JOIN SubCodesTable s ON s.CodeA = r.CodeA " +
"where SubCodeB = '" + b_sub + "' AND r.CodeB = '" + b_code + "'");
And the results are returned as a String[] and always seem to be in the order of
[CodeA, SubCodeA, CodeB, SubCodeB]
but I have only tested this locally and can't find in the documentation what determines the order for variables in the array that is returned.
The results are ordered that way because that is the order in which you specified them in the select statement. If you want the results ordered in a different way, reorder them in your query.
If anyone is looking for a way to know column names when using "select *" you can also use "getColumnNames()" on the rawResults object and they will always be in the order that the results are. Examples
//The result is returned as a GenericRawResults object
List<String[]> results = rawResults.getResults();
String[] columns = rawResults.getColumnNames();
JSONObject obj = new JSONObject();
if(results.size()>0)
{
obj.put(columns[0], results.get(0)[0]);
obj.put(columns[1], results.get(0)[1]);
obj.put(columns[2], results.get(0)[2]);
obj.put(columns[3], results.get(0)[3]);
}

Get multiple values from querying db with entity framework

I've been thinking this for a while. Is there an easy way to use the result querying a database twice without storing the result of the query in some variable? Say I have a
string ResearchAdmin;
where I want to put the 'FirstName' and 'Surname' found in 2 different columns in a 'ProjectResearcher' table in the database. Can I query the database just once (using say entity framework), and get both columns without storing the entire table's data.
To illustrate my point, doing the code below will I think query the database twice, once to get the 'FirstName', once to get the 'Surname':
ResearchAdmin = db.ProjectResearcher.FirstOrDefault(r => r.ProjectId == project.ProjectId).Researcher.FirstName + " " + db.ProjectResearcher.FirstOrDefault(r => r.ProjectId == project.ProjectId).Researcher.Surname
To run the query once I can do the following:
Researcher researchAdmin = db.ProjectResearcher.FirstOrDefault(r => r.ProjectId == project.ProjectId).Researcher;
String researchAdminName = researchAdmin.FirstName + " " + researchAdmin.Surname;
What I'm wondering is if I can do the first option somehow without querying the database twice.
You could do something like this:
String researchAdminName = db.ProjectResearcher.Where(r => r.ProjectId == project.ProjectId)
.Select(r => r.FirstName + " " + r.Surname).FirstOrDefault();
Just have to be a little careful that whatever you are putting into the select statement is supported by linq to entities, but simple string concatenation is.
Thewads answer looks correct and it will give you what you need.
An alternative:
Wrap logic in Stored Proc (certainly an overkill here) but for more complex manipulation its prob. better as SQL server will have a cached plan and will be faster.

Update multiple rows with WHERE clause

I am trying to update multiple rows at once (SQL Server 2005). Previously I was updating a single row with this query:
UPDATE dbo.My_Users
SET MyUserId = #MyUserId
WHERE EmailID = #EmailId
Now #EmailId will have comma-separated EmailIds.
How can I modify the script to update multiple rows? I have seen some examples which make use of UNION ALL. But they are mostly to insert multiple records without where clause.
A similar question was answered in Parameterize an SQL IN clause
The same idea can be applied here:
declare #EmailIds varchar = '|email1#test.com|email2#test.com|';
UPDATE dbo.My_Users SET MyUserId=#MyUserId WHERE #EmailIds LIKE '%|' + EmailID + '|%';
Though this does not contain a comma-separated list, the delimiter could easily be changed to a pipe-character. The caveat here is, the more data that exists in the table and the more email addresses that are in the #EmailIds list, the slower (much slower) this query can become.
Using C#, I would actually recommend the second example in the above-mentioned question where the list is expanded to create a query similar to:
UPDATE dbo.My_Users SET MyUserId=#MyUserId WHERE EmailID IN (#email1, #email2);
C# to implement (a modified version of the example in the question above):
string[] emails = new string { "email1#test.com", "email2#test.com" };
string sql = "UPDATE dbo.My_Users SET MyUserId=#MyUserId WHERE EmailID IN ({0});"
string[] emailParams = emails.Select((s, i) => "#email" + i.ToString()).ToArray();
string inClause = string.Join(",", emailParams);
using (SqlCommand cmd = new SqlCommand(string.Format(sql, inClause))) {
for(int i = 0; i < emailParams.Length; i++) {
cmd.Parameters.AddWithValue(emailParams[i], emails[i]);
}
}
You could use dynamic SQL
exec('UPDATE dbo.My_Users SET MyUserId = ' + cast(#MyUserId as varchar) + ' WHERE EmailID in (' + #EmailIds + ')')