Entity Framework cast selected fields to varchar and concat them - sql

I want do below query in Entity Framework
select
cast(p_min as varchar) + '' + cast(p_max as varchar)
from
user_behave_fact
where
beef_dairy_stat = 'True' and param_id = 2
group by
p_min,p_max
go

Since you have not mentioned a language, I am writing code in C#.
Try this:
using (var dbContext = new DatabaseContext())
{
var output = (
from fact in dbContext.user_behave_facts
where fact.beef_dairy_stat == "True" && fact.param_id == 2
group fact by new {fact.p_min, fact.p_max} in grp
select new
{
ColName = grp.Key.p_min.ToString() + " " + grp.Key.p_max.ToString()
}
).ToList();
}
.ToList() can be changed according to your expectations

Related

Converting comma-separated value to in subquery

I have following query :
Set #OrderStatuses = 'Cancelled,Complete'
Select *
From TableName
Where Status in (#OrderStatuses)
The Status is what I am receiving externally and it fails to fetch any result as, what we actually need to process is:
Select *
From TableName
Where Status in ('Cancelled', 'Complete');
#OrderStatuses can contain any number of comma-separated values.
One method is dynamic SQL:
declare #sql nvarchar(max);
set #sql = 'Select * from TableName Where Status in (#list)';
set #sql = replace(#sql, '#list', '#OrderStatuses');
exec sp_executesql #sql;
Note: You cannot pass a list in as a parameter.
You can also use like:
Select *
from TableName
Where ',' + #OrderStatuses + ',' like '%,' + Status + ',%';
However, this cannot use an index for the the comparison.
You will need to use split string function and process the rest..
;with cte
as
(
select * from split_strings(#orderstatus,',')
)
select * from table where status in (select item from cte)
You must add the list as a Table-Valued Parameter
Here are two methods I use to convert any IEnumerable list of items (in this case, integers) into a Table Valued Parameter. You have to have created/defined a User Defined type (UDT) for the resultant table in your database. In the example below the UDT is named dbo.keyIds and is created (once) with this SQL:
CREATE TYPE [dbo].[KeyIds]
AS TABLE(pkId int NOT NULL, PRIMARY KEY CLUSTERED
( [pkId] ASC) WITH (IGNORE_DUP_KEY = OFF)
)
The c# code is:
public class DbParamList : List<IDbDataParameter>
{
public void AddSQLTableParm<T>(
string parmName, IEnumerable<T> values)
{
var parm = new SqlParameter(parmName, CreateDataTable(values))
{
SqlDbType = SqlDbType.Structured,
TypeName = "dbo.keyIds"
};
Add(parm);
}
internal static DataTable CreateDataTable<T>(IEnumerable<T> values)
{
var dt = new DataTable();
var props = typeof (T).GetProperties();
if (props.Length > 0)
{
foreach (var col in props)
dt.Columns.Add(col.Name, col.PropertyType);
foreach (var id in values)
{
var newRow = dt.NewRow();
foreach (var prop in id.GetType().GetProperties())
newRow[prop.Name] = prop.GetValue(id, null);
dt.Rows.Add(newRow);
}
}
else
{
dt.Columns.Add("ids");
foreach (var id in values) dt.Rows.Add(id);
}
return dt;
}
}

Dynamic SQL with servlets

I have a servlet called DBChart mapped to url /db.the servlet outputs some data based on the sql query used here.
What I have:
At client end, I am making an ajax call like this:
$.ajax({
type : 'POST',
async: false,
url : 'http://localhost:8080/DBCHART/db',
success : function(data) {/*some code*/})
and At server end, a static query that says:
String sql ="select * from Employee"
What I want:
I want to be able to pass some parameters here like :
url: http://localhost:8080/DBCHART/db?Name = 'xyz'?Age = 21
and at server end, the query in this case should become:
select * from Employee where Name ='xyz' and Age = 21
i.e only if those parameters were supllied otherwise it should stay
select * from Employee
Can I please get some direction to create dynamic sql for this efficiently?
let's say in this case you're using varName as 'xyz' and varAge as 21
-- -- Name = 'xyz'?Age = 21
you can use some logic like this (point to ponder: WHERE 1 = 1 )
string sqlQuery = " select * from Employee where 1 = 1 ";
if(null != varName && !varName.isEmpty())){
// add criteria for Name
sqlQuery += " AND Name = '"+ varName + "'"; // TODO: use parametrized query
}
if(null != varAge && varAge > 0){
// add criteria for Age
sqlQuery += " AND Age = "+ varAge ; // TODO: use parametrized query
}

DataContext.ExecuteQuery<object> returns object {}

I'm trying to write function for selecting optional columns in linq(columns that may not exist). The problem is in linq like this:
using (DataDataContext db = new DataDataContext()){
var collection = from t in table
select new
{
Nonoptional = t.A;
Optional = IsInDB("table","B") ? t.B : -1; //this is optional column
}}
Unfortunately, this won't work because the fragment near Optional will be translated to case statement and error arises that column not exists.
So i decided to "cover" it with function:
using (DataDataContext db = new DataDataContext()){
var collection = from t in table
select new
{
Nonoptional = t.A;
Optional = IsInDB("table","B") ? OptionalColumnValue<int>("table","B","id_table",t.id_table) : -1; //this is optional column
}}
I want this function to be universal. It should work like that" If there is no value or column is nullable and value is null then return default value for type.
I came up with something like this:
//table,column - obvious,id_column - PK column of table, id - id of currently processing record
public static T OptionalColumnValue<T>(string table,string column,string id_columm,int id) T t = default(T);
DataDataContext db = new DataDataContext();
IEnumerable<object> value = db.ExecuteQuery<object>("select " + column + " from " + table + " where " + id_columm + " = " + id.ToString());
List<object> valueList = value.ToList();
if (valueList.Count == 1)//here is the problem
t = (T)valueList.First();
return t;
}
When there is null value db.ExecuteQuery return something like object{}. I'm assuming this is "empty" object,with nothing really in there. I was thinking about checking for "emptiness" of this object( BTW this is not DBull).
When i realised that this is no way either with concrete value in this column(it cannot cast it to return correct type), then I tried db.ExecuteQuery<T>. Then concrete value - OK, null - Exception.
I thought, maybe Nullable<T> as return value. Nop, because string also can be T.
I don't know what to do next. Maybe there's another solution to this problem.

LinqPad "ORA-00933: SQL command not properly ended" error

I got the error: ORA-00933: SQL command not properly ended when run the follow linq query at LinqPad V4.42.14(AnyCPU), database is Oracle 11g.
If I replace
where coof.CoofCode == tod.PatTrnsplntFail.CoofCode && coof.OrgCode == prod.OrgCode
to
where coof.CoofCode == tod.PatTrnsplntFail.CoofCode
it works, but I can not remove that factor.
Any body can help me out will be great appreciate.
void Main()
{
var q = (from pat in Pats
from patr in pat.PatRegisters
from prod in patr.PatRegisterOrgDets
from tod in prod.TransplantOrgDets
select new {
PatId = pat.PatID,
FullName = pat.FirstName + ", " + pat.LastName,
RegisterDate = patr.RegDate.ToString("yyyy-MMM-dd"),
TransplantDate = tod.Transplant.TransplantDate.ToString("yyyy-MMM-dd"),
OrganSpec = tod.OrgSpec.Descrip,
IsTransplantedFailed = tod.PatTrnsplntFail.TodID == 0 ? false: true,
TransplantedFailReason = from coof in CausesOfOrgFail
where coof.CoofCode == tod.PatTrnsplntFail.CoofCode && coof.OrgCode == prod.OrgCode
select coof.Descrip
}).Distinct().OrderBy(o => o.PatId);
q.Dump(true);
}
I found a work around way to avoid the issue, but acturally I do not think this is a good way, I fell the LinqPad Oracle Driver has internal bugs cause that issue. Joeseph if you could read this, please give your suggestion. So use the follow linq query instead:
void Main()
{
var q1 = (from pat in Pats
from patr in pat.PatRegisters
from prod in patr.PatRegisterOrgDets
from tod in prod.TransplantOrgDets
where tod.PatTrnsplntFail.TodID == null
select new {
PatId = pat.PatID,
FullName = pat.FirstName + ", " + pat.LastName,
RegisterDate = patr.RegDate.ToString("yyyy-MMM-dd"),
TransplantDate = tod.Transplant.TransplantDate.ToString("yyyy-MMM-dd"),
OrganSpec = tod.OrgSpec.Descrip,
IsTransplantedFailed = false,
CausesOfOrgFailReason = ""
}).Distinct().OrderBy(o => o.PatId);
var q2 = (from pat in Pats
from patr in pat.PatRegisters
from prod in patr.PatRegisterOrgDets
from tod in prod.TransplantOrgDets
from coof in CausesOfOrgFail where coof.CoofCode == tod.PatTrnsplntFail.CoofCode && coof.OrgCode == prod.OrgCode
where tod.PatTrnsplntFail.TodID != null
select new {
PatId = pat.PatID,
FullName = pat.FirstName + ", " + pat.LastName,
RegisterDate = patr.RegDate.ToString("yyyy-MMM-dd"),
TransplantDate = tod.Transplant.TransplantDate.ToString("yyyy-MMM-dd"),
OrganSpec = tod.OrgSpec.Descrip,
IsTransplantedFailed = true,
CausesOfOrgFailReason = coof.Descrip
}).Distinct().OrderBy(o => o.PatId);
q1.ToList().Union(q2.ToList()).OrderBy(o => o.PatId).Dump(true);
}

LINQ to SQL C# COALESCE

Given the following table:
Length | Width | Color | ID
===========================
18 | 18 | blue | 1
---------------------------
12 | 12 | red | 1
---------------------------
I want to produce a single column/row:
SIZES
=================
18 x 18, 12 x 12,
I can do this in SQL as follows:
DECLARE #SIZES VARCHAR(8000)
SELECT #SIZES = COALESCE(#SIZES, '') + Convert(varchar(80), [Length]) + ' x ' +
Convert(varchar(80), [Width]) + ', '
FROM table
where ID = 1
GROUP BY [Length], [Width]
ORDER BY [Length], [Width]
SELECT SIZES = #SIZES
But I cannot figure out how to do this in LINQ.
The closest I got was:
from t in table
where id == 1
group t by new {
t.Length,
t.Width
} into g
orderby g.Key.Length, g.Key.Width
select new {
SIZES = (Convert.ToInt32(g.Key.Length) + " x " +
Convert.ToInt32(g.Key.Width) + ", ")
}
Which produces one column and two rows:
SIZES
========
18 x 18,
12 X 12,
The converts are unimportant to the problem. The columns are defined as floats though all are integers. The key is the COALESCE function I cannot figure out how to do that in LINQ.
Try ?? (null coalesce operator) like:
t.Length ?? 0
I don't think LINQ to SQL supports this T-SQL trick. The COALESCE isn't really the issue (as Mehrdad points out the equivalent in C# is ??) -- it's the fact that SQL Server aggregates each result via string concatenation into the variable #SIZES. AFAIK LINQ to SQL can't construct this type of query.
This will yield your desired result, but the string concatenation is performed on your side, not on the SQL server side. That probably doesn't matter.
var query =
from t in table
where id == 1
group t by new {
t.Length,
t.Width
} into g
orderby g.Key.Length, g.Key.Width
select new {
SIZES = (Convert.ToInt32(g.Key.Length) + " x " +
Convert.ToInt32(g.Key.Width) + ", ")
};
var result = string.Join(string.Empty, query.Select(r => r.SIZES).ToArray());
I would just return the int sizes from SQL and do the string building client-side:
var query =
from t in table
where id == 1
group t by new {
t.Length,
t.Width
} into g
orderby g.Key.Length, g.Key.Width
select g.Key;
var sizeStrings = from s in query.AsEnumerable()
select string.Format("{0} x {1}", s.Length, s.Width);
var result = string.Join(", ", sizeStrings.ToArray());
You could use the .Aggregate function, like so:
(from t in table
where id == 1
group t by new {
t.Length,
t.Width
} into g
orderby g.Key.Length, g.Key.Width
select new {
SIZES = (Convert.ToInt32(g.Key.Length) + " x " +
Convert.ToInt32(g.Key.Width) + ", ")
}).Aggregate((x,y) => x + y)
This should kick out a single string, like you want.
Aggregate just internally maintains the exact same variable you had defined in the SQL, just implicitly.