How to get a variable replaced with a field name in a LINQ? - asp.net

string companyName="ABC";
var query = from q in context.Company where q.CompanyName == companyName select q;
Is there any way to replace the q.CompanyName part of the query with a string variable
so that the field used for filtering be a parametric?
I tried
string str1 = "companySize";
string str2 = "q." + str1;
string companySize = "Mid";
var query = from q in context.Company where str2 == companySize select q;
Didn't work.
Been trying to let the user choose the columns for the query.

Read more about both below option at : Dynamic query with Linq
you can use one of this
Use Dynamic LINQ library
Example for the the blog below
string strWhere = string.Empty;
string strOrderBy = string.Empty;
if (!string.IsNullOrEmpty(txtAddress.Text))
strWhere = "Address.StartsWith(\"" + txtAddress.Text + "\")";
if (!string.IsNullOrEmpty(txtEmpId.Text))
{
if(!string.IsNullOrEmpty(strWhere ))
strWhere = " And ";
strWhere = "Id = " + txtEmpId.Text;
}
if (!string.IsNullOrEmpty(txtDesc.Text))
{
if (!string.IsNullOrEmpty(strWhere))
strWhere = " And ";
strWhere = "Desc.StartsWith(\"" + txtDesc.Text + "\")";
}
if (!string.IsNullOrEmpty(txtName.Text))
{
if (!string.IsNullOrEmpty(strWhere))
strWhere = " And ";
strWhere = "Name.StartsWith(\"" + txtName.Text + "\")";
}
EmployeeDataContext edb = new EmployeeDataContext();
var emp = edb.Employees.Where(strWhere);
Predicate Builder
EXample
var predicate = PredicateBuilder.True<employee>();
if(!string.IsNullOrEmpty(txtAddress.Text))
predicate = predicate.And(e1 => e1.Address.Contains(txtAddress.Text));
if (!string.IsNullOrEmpty(txtEmpId.Text))
predicate = predicate.And(e1 => e1.Id == Convert.ToInt32(txtEmpId.Text));
if (!string.IsNullOrEmpty(txtDesc.Text))
predicate = predicate.And(e1 => e1.Desc.Contains(txtDesc.Text));
if (!string.IsNullOrEmpty(txtName.Text))
predicate = predicate.And(e1 => e1.Name.Contains(txtName.Text));
EmployeeDataContext edb= new EmployeeDataContext();
var emp = edb.Employees.Where(predicate);

If you don't want to use libraries like dynamicLINQ, you can just create the Expression Tree by yourself:
string str1 = "companySize";
string str2 = "q." + str1;
string companySize = "Mid";
var param = Expression.Parameter(typeof(string));
var exp = Expression.Lambda<Func<Company, bool>>(
Expression.Equal(
Expression.Property(param, str1),
Expression.Constant(companySize)),
param);
var query = context.Company.Where(exp);

I think the best way to do this is with built in libraries (and PropertyDescriptor type).
using System.ComponentModel;
void Main()
{
Test test = new Test();
test.CompanyName = "ABC";
object z = TypeDescriptor.GetProperties(test).OfType<PropertyDescriptor>()
.Where(x => x.Name == "CompanyName").Select(x => x.GetValue(test)).FirstOrDefault();
Console.WriteLine(z.ToString());
}
public class Test
{
public string CompanyName { get; set; }
}

Related

Oracle "UPDATE" command returns 0 rows affected in my ASP .NET application but the SQL statement itself works in PL/SQL

I have this ASP.NET project working with Oracle, I have the following code for operating the DB:
public int cmd_Execute_Orcl(string strSql, params OracleParameter[] paramArray)
{
OracleCommand myCmd = new OracleCommand();
try
{
myCmd.Connection = myOrclConn;
myCmd.CommandText = strSql;
foreach (OracleParameter temp in paramArray)
{
myCmd.Parameters.Add(temp);
}
ConnectionManage(true);
int i = myCmd.ExecuteNonQuery();
myCmd.Parameters.Clear();
return i;
}
catch (Exception ex)
{
throw (ex);
}
finally
{
myCmd.Dispose();
ConnectionManage(false);
}
}
"ConnectionManage()" turns on or off the connection, the following code is from data access layer of the program:
public string Edit_DAL(string id, string jh, string jz, string jd, string wd, string gzwz, string qxlx, string sx, string jx, string jb, string cfdd, string zjqssj, string zjzzsj, string bz)
{
string sql = "update JH set jh = :jh, jz = :jz, wd = :wd, jd = :jd, gzwz = :gzwz, qxlx = :qxlx, sx = :sx, jx = :jx, jb = :jb, cfdd = :cfdd, zjqssj = TO_DATE(:zjqssj, 'yyyy-mm-dd hh24:mi:ss'), zjzzsj = TO_DATE(:zjzzsj, 'yyyy-mm-dd hh24:mi:ss'), bz = :bz where ID = :idy";
string result = null;
{
String[] temp1 = zjqssj.Split('/');
String[] temp2 = zjzzsj.Split('/');
string tempString = "";
if (temp1[2].Length < 2)
{
temp1[2] = temp1[2].Insert(0, "0");
}
for (int i = 0; i < temp1.Length; i++)
{
if (i != 0)
{
temp1[i] = temp1[i].Insert(0, "/");
}
tempString += temp1[i].ToString();
}
zjqssj = tempString;
tempString = "";
if (temp2[2].Length < 2)
{
temp2[2] = temp2[2].Insert(0, "0");
}
for (int i = 0; i < temp2.Length; i++)
{
if (i != 0)
{
temp2[i] = temp2[i].Insert(0, "/");
}
tempString += temp2[i].ToString();
}
zjzzsj = tempString;
tempString = "";
}
OracleParameter[] pars ={
new OracleParameter(":idy",id),
new OracleParameter(":jh",jh),
new OracleParameter(":jz",jz),
new OracleParameter(":jd",jd),
new OracleParameter(":wd",wd),
new OracleParameter(":gzwz",gzwz),
new OracleParameter(":qxlx",qxlx),
new OracleParameter(":sx",sx),
new OracleParameter(":jx",jx),
new OracleParameter(":jb",jb),
new OracleParameter(":cfdd",cfdd),
new OracleParameter(":zjqssj",(zjqssj.Replace('/', '-') + " 00:00:00")),
new OracleParameter(":zjzzsj",(zjzzsj.Replace('/', '-') + " 00:00:00")),
new OracleParameter(":bz",bz)
};
try
{
SqlHelper.cmd_Execute_Orcl(sql, pars);
result = "ok";
}
catch (Exception ex)
{
result = "no" + "=" + ex.Message + "\n" + ex.StackTrace;
}
return result;
}
Here's where the strange thing happens, when I hit this part of the code, there's no exception, it returns 0, no rows affected, all the values of the parameters are normal, with expected value, then I tried to run the command in PL/SQL and it works, the row is correctly updated, delete function is also referencing the same "cmd_Execute_Orcl" method and it works just fine, and for the other object the edit function is working perfectly, I am posting the code below:
public string Edit(string OriginalId, string EditUserAccount, string EditUserName, string EditUserMobile, string EditDeptId, string EditRoleId, string EditRoleName)
{
string sql = "update AuthUser set UserAccount=:EditUserAccount, UserName=:EditUserName, UserMobile=:EditUserMobile, DepartmentId=:EditDeptId, RID=:EditRoleId, RoleName=:EditRoleName where ID=:OriginalId";
OracleParameter[] pars ={
new OracleParameter(":EditUserAccount",EditUserAccount),
new OracleParameter(":EditUserName",EditUserName),
new OracleParameter(":EditUserMobile",EditUserMobile),
new OracleParameter(":EditDeptId",EditDeptId),
new OracleParameter(":EditRoleId",EditRoleId),
new OracleParameter(":EditRoleName",EditRoleName),
new OracleParameter(":OriginalId",OriginalId),
};
try
{
SqlHelper.cmd_Execute_Orcl(sql, pars);
return "ok";
}
catch (Exception ex)
{
string test = ex.Message;
return "no";
}
}
In the expected table, column ID is nvarchar2 with default value of sys_guid(), column ZJQSSJ and column ZJZZSJ is of type date, all other columns are of type varchar2, I have also tried executing "COMMIT" and reformating data for date, but the same problem is still there, plz help...

Conversion failed when converting the varchar to data type int: SQL

I am creating a web app in asp.net mvc I have a query which looks like below
using (SqlConnection conn = new SqlConnection(_connStr))
{
conn.Open();
var p = new DynamicParameters();
p.Add("#SP_RoleId", "7,8,9", dbType: DbType.String, direction: ParameterDirection.Input);
p.Add("#SP_UserId", userId, dbType: DbType.Int32, direction: ParameterDirection.Input);
var obj = conn.Query<PendingKmsRequest>(sql: "SELECT [f].[id] AS [FileId],[fvr].[Id] AS [RequestId], [au].[Name]"
+ ", [fvr].[RequestByUserId], [fvr].[FromDate], [fvr].[ToDate],[f].[Title], [fvr].[Status], [fvr].[StatusRemarks]"
+ "FROM [dbo].[File] AS[f]"
+ "INNER JOIN [dbo].[FileViewRequest] AS [fvr] ON [f].[CurrentFileVersionId] = [fvr].[FileVersionId]"
+ "INNER JOIN [Access].[User] AS [au] ON [fvr].[RequestByUserId] = [au].[Id]"
+ "WHERE ([fvr].[Status] = 'P' OR ([fvr].[Status] = 'A' AND [fvr].[StatusByUserId] = #SP_UserId AND GETDATE() BETWEEN [fvr].[FromDate] AND [fvr].[ToDate]))"
+ "AND (SELECT 1 FROM [Access].[UserRoleMap] WHERE UserId=#SP_UserId AND RoleId IN(#SP_RoleId)) = 1", param: p, commandType: CommandType.Text);
if (obj != null && obj.Count() > 0)
return obj.ToList();
else
return new List<PendingKmsRequest>();
}
NOTE: Role id is always like (7,8,9) and it is int column in the database.
I get this conversion error on this line of code:
WHERE UserId = #SP_UserId AND RoleId IN (#SP_RoleId))
This is the error:
Conversion failed when converting the nvarchar value '7,9,10' to data type int.
How can I prevent this error?
The following line in your question code:
p.Add("#SP_RoleId", "7,8,9", dbType: DbType.String, direction: ParameterDirection.Input);
The value "7,8,9" is string and parameter type DbType.String is string as well.
But, you said this is int in your database. This is mismatch.
Further, your query:
WHERE UserId = #SP_UserId AND RoleId IN (#SP_RoleId))
The query is using IN clause.
Dapper can convert your value for IN clause if pass in an IEnumerable.
Change the line of code as below:
p.Add("#SP_RoleId", new[] {7,8,9}, dbType: DbType.Int32, direction: ParameterDirection.Input);
No need to use convert string in array or any string split() function
If you have comma saperated string then you can check it like below steps,
If you have #SP_RoleId = "7, 8, 9"
You can convert this string as below
#SP_RoleId = ",7,8,9," ( ',' + ltrim(rtrim( #SP_RoleId )) + ',' )
Now use Like to check ,UserId,
Updated code as below,
using (SqlConnection conn = new SqlConnection(_connStr))
{
conn.Open();
var p = new DynamicParameters();
p.Add("#SP_RoleId", "7,8,9", dbType: DbType.String, direction: ParameterDirection.Input);
p.Add("#SP_UserId", userId, dbType: DbType.Int32, direction: ParameterDirection.Input);
var obj = conn.Query<PendingKmsRequest>(sql: "SELECT [f].[id] AS [FileId],[fvr].[Id] AS [RequestId], [au].[Name]"
+ ", [fvr].[RequestByUserId], [fvr].[FromDate], [fvr].[ToDate],[f].[Title], [fvr].[Status], [fvr].[StatusRemarks]"
+ "FROM [dbo].[File] AS[f]"
+ "INNER JOIN [dbo].[FileViewRequest] AS [fvr] ON [f].[CurrentFileVersionId] = [fvr].[FileVersionId]"
+ "INNER JOIN [Access].[User] AS [au] ON [fvr].[RequestByUserId] = [au].[Id]"
+ "WHERE ([fvr].[Status] = 'P' OR ([fvr].[Status] = 'A' AND [fvr].[StatusByUserId] = #SP_UserId AND GETDATE() BETWEEN [fvr].[FromDate] AND [fvr].[ToDate]))"
+ "AND (SELECT 1 FROM [Access].[UserRoleMap] WHERE ',' + lTrim(rTrim(#SP_RoleId)) + ',' like '%,' + lTrim(rTrim(UserId) + ',%' " // Updated line
+ "AND RoleId IN(#SP_RoleId)) = 1", param: p, commandType: CommandType.Text);
if (obj != null && obj.Count() > 0)
return obj.ToList();
else
return new List<PendingKmsRequest>();
}

How to correctly return from stored procedure in Sql to model?

I need to return list of values from stored procedure to my model. How do I do it:
[HttpGet("{id}")]
public DataSource Get(int id)
{
DataSource ds = _dbContext.DataSources.Where(d => d.Id == id)
.Include(d => d.DataSourceParams)
.ThenInclude(p => p.SelectOptions).FirstOrDefault();
foreach(DataSourceParam p in ds.DataSourceParams)
{
if(p.TypeId == 5)
{
p.SelectOptions = _dbContext.SelectOptions.FromSql("Exec " + ds.DataBaseName + ".dbo." + "procGetTop50 " + ds.Id + ", 1").ToList();
}
}
return ds;
}
First, declare your procedure with parameters:
string sql = "myProcedure #param1, #param2";
Second, create parameters
var param1 = new SqlParameter { ParameterName = "param1", Value = param1Value};
var param2 = new SqlParameter { ParameterName = "param2", Value = param2Value };
Finally, exec the code:
info = this.DbContext.Database.SqlQuery<MyModel>(sql, param1, param2).FirstOrDefault();
This is it!
Just remember your model must match with the procedure columns. With means, if your procedure returns a column named 'MyProp' your model 'MyModel' must have a 'MyProp' property.

asp:calendar binds last value to date from database

I have to bind an <asp:calendar> with data fetched from a database using a linq query.
Here is the linq code
public List<AllCalander> SearchCalender(int month, int zip, string type, int cause)
{
var xyz = (from m in DB.Calenders
where(m.DateFrom.Value.Month==month || m.Zip==zip || m.ActivityType==type || m.CauseID==cause)
group m by new { m.DateFrom } into grp
select new
{
caustitle = grp.Select(x => x.Caus.CauseTitle),
datfrm = grp.Key.DateFrom,
total = grp.Count()
})
.ToList()
.Select(m => new AllCalander
{
DateFrom =Convert.ToDateTime(m.datfrm),
CauseTitle = string.Join(",", m.caustitle),
Total = m.total
});
My aspx.cs code is here
List<AllCalander> calnder = calbll.SearchCalender(mnth,ZipString,type,causeString);
foreach (var myItem in calnder)
{
string datetime = myItem.DateFrom.ToString();
Literal myEventNameLiteral = new Literal();
myEventNameLiteral.ID = i + myItem.CauseID.ToString();
// string currentcalanderDate = e.Day.Date.Day.ToString() ;
if (string.Equals(DateTime.Parse(datetime).ToString("MMM dd yyyy"), e.Day.Date.ToString("MMM dd yyyy")))
{
string a = myItem.CauseTitle;
if (a != cause)
cause = a;
coun++;
myEventNameLiteral.Mode = LiteralMode.PassThrough;
myEventNameLiteral.Text = "<br /><span style='font-family:verdana; font-size:10px;'>" + myItem.CauseTitle + "(" + myItem.Total + ")"+ " ";
e.Cell.Controls.Add(myEventNameLiteral);
}
i++;
}
but on output it only shows the last value from database instead of showing all the data.
Can somebody please tell me what's wrong?
Thanks in advance
group m by new { m.DateFrom, m.Caus.CauseTitle } into grp

Accessing records in Android using rawQuery and then displaying

I am working on several rawQueries to use to parse data from a table in Android. The below code works fine and returns the lowest rowid in the table.
public void firstRecord(View v){
Cursor c = db.rawQuery("SELECT * FROM surveyDB WHERE rowid = (SELECT MIN(rowid) FROM surveyDB)",null);
c.moveToFirst();
szList.add(c.getString(0));
Toast.makeText(getApplicationContext(), "Sucessful Event. szRowid is: " +szList +".", Toast.LENGTH_LONG).show();
}
I have two questions, and they are both extremely basic: 1) what is the best way to expand the above code to create language to capture the contents of other columns in this table at that specific rowid, (rowid, sampler, species, place), and display this in my application? Something like this perhaps:
((EditText)findViewById(R.id.edSpecies)).setText("");
with the proper reference replacing "" in .setText()?
String TABLE_SURVEY = "surveyDB";
String COL_ROW_ID = "rowid";
String COL_SAMPLER = "sampler";
String COL_SPECIES = "species";
String COL_PLACE = "place";
public ArrayList<SurveyRecord> getSurveyRecords()
{
ArrayList<SurveyRecord> records = new ArrayList<SurveyRecord>();
String query = "SELECT * FROM " + TABLE_SURVEY;
query += " WHERE " + COL_ROW_ID = " SELECT MIN ("
query += COL_ROW_ID + ") FROM " + TABLE_SURVEY;
Cursor c = db.rawQuery(query,null);
if(Cursor.moveToFirst())
{
do{
String sampler = c.getString(cursor.getColumnIndex(COL_SAMPLER));
String species= c.getString(cursor.getColumnIndex(COL_SPECIES));
String place = c.getString(cursor.getColumnIndex(COL_PLACE));
String rowId = c.getString(cursor.getColumnIndex(COL_ROW_ID));
records.add(new (rowId,species,place,sampler));
}while(c.moveToNext())
}
c.close();
}
public class SurveyRecord{
String mRowId;
String mSpecies;
String mPlace;
String mSampler;
public SurveyRecord(String rowId,String species,String place,String sampler)
{
this.mRowId = rowId;
this.mSpecies = species;
this.mPlace = place;
this.mSampler = sampler;
}
}
//Goes to the first record in the dataset
public void firstRecord(View v){
Cursor c = db.rawQuery("SELECT * FROM surveyDB WHERE rowid = (SELECT MIN(rowid) FROM surveyDB)",null);
c.moveToFirst();
((EditText)findViewById(R.id.edRowid))
.setText(c.getString(0));
((EditText)findViewById(R.id.edSpecies))
.setText(c.getString(1));
((EditText)findViewById(R.id.edArea))
.setText(c.getString(2));
((EditText)findViewById(R.id.edSampler))
.setText(c.getString(3));
}

Resources