Blazor .net core ref enum? param not changing its value - visual-studio

Im a bit confused with whats happening bellow:
Can anyone explain me why is dataType keep saying StatisticData instead of SibsMonthly??
dataType is a enum? passad as ref param to this method and its initialized as null before the method call..
Here is the code:
string errorMessage = null;
Enums.Uploads.DataType? dataType = null;
if (ValidadeFile(file, ref errorMessage, ref dataType))
{
...
}
private bool ValidadeFile(IBrowserFile file, ref string errorMessage, ref Enums.Uploads.DataType? dataType)
{
List<string> acceptedFileTypes = new List<string>
{
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
};
var valid = true;
if (AcceptedFileNames != null && AcceptedFileNames.Length > 0)
{
var tmp = AcceptedFileNames.Where(x => new Regex(x.Regex).IsMatch(file.Name))
.OrderByDescending(x => x.DataType)
.Select(x => x.DataType)
.FirstOrDefault();
dataType = tmp;
if (dataType == null)
{
valid = false;
errorMessage = Constants.Uploads.Error.InvalidFileName;
}
}
...
}

The WASM debugger doesn't seem to like ref variables, it seems to look at their address, not their value:
Inspecting them at their call site or in the Debug window behaves as expected; this is a debugger isssue.

Related

How to call Expression Func with two input parameters

I have following Expression Func which is receiving two input paramters, first is Person Object, second is bool and returning another type of Object PersonProfile
private Exression<Func<Person, bool, PersonProfile>> PersonProfileProjection => (person, isValid) =>
new PersonProfile
{
FirstName = person.FirstName,
HasAddress = isValid ? person.Address1 : null
};
And I am trying to call this while fetching Person table from dbContext.
_dbContext.Persons.Select(PersonProfileProjection);
I am confused how to send boolean parameter inside PersonProfileProjection. It works when I only put one input and one output parameter like this. But I want extra boolean input as well.
Any help would be highly appreciated.
You can follow Microsoft documentation for this : Expression Class
One sample created for SQLite that show above function usage.
public void GetData()
{
var connection = new SQLiteConnection(#"Data Source=database.sqlite;Version=3;");
var context = new DataContext(connection);
connection.Open();
var createtableQuery = #"
drop table Company;
CREATE TABLE[Company]
(
[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
[Seats] INTEGER NOT NULL
);
";
var command = new SQLiteCommand(createtableQuery, connection);
command.ExecuteNonQuery();
Company com = new Company()
{
Id = 6,
Seats = 7
};
context.GetTable<Company>().InsertOnSubmit(com);
context.SubmitChanges();
var companies = context.GetTable<Company>();
foreach (var company in companies)
{
Console.WriteLine("Company: {0} {1}",
company.Id, company.Seats);
}
//compile Expression using Compile method to invoke it as Delegate
Func<int,int, Company> PersonProfileProjectionComp = PersonProfileProjection.Compile();
var dd = companies.Select(p => PersonProfileProjectionComp(p.Id,p.Seats));
//// Below line inline use. Both works.
//var dd = companies.Select(p => PersonProfileProjection.Compile().Invoke(p.Id,p.Seats));
}
private System.Linq.Expressions.Expression<Func<int, int, Company>> PersonProfileProjection => (person, seats) =>
new Company
{
Id = person,
Seats = seats
};
or in one line use this :
PersonProfileProjection.Compile().Invoke(person, isValid)
You could declare it as a Func instead of an expression:
private Func<Person, bool, PersonProfile> PersonProfileProjection => (person, isValid) =>
new PersonProfile
{
FirstName = person.FirstName,
HasAddress = isValid // do what you meant to do
};
... and call it as:
_dbContext.Persons.Select(p => PersonProfileProjection(p, true));
You could as well write an ordinary method:
private PersonProfile PersonProfileProjection(Person person, bool isValid)
{
return new PersonProfile
{
FirstName = person.FirstName,
HasAddress = isValid // do what you want to do
};
}
...and call it the same way:
_dbContext.Persons.Select(p => PersonProfileProjection(p, true));

Cannot convert from object to string error

Hi I have code like this :
foreach (DataRow dr in upCSV.Rows)
{
ObjectParameter getCustomField1 = new ObjectParameter("CustomField1", String.IsNullOrEmpty(dr["CustomField1"]) ? null : Convert.ToInt32(dr["CustomField1"]));
var results = ordertable.usp_AppUpdateUserData(Convert.ToInt32( getCustomField1) )
}
Here I am getting error as Cannot convert from object to string .
Here Customefield1 is of int type and it has null value. So when i debug, it is showing value for customfield1 as " ". So how can I convert this to int and pass it to my Stored procedure ?
You can cast your dr["CustomField1"] object directly to an int?:
foreach (DataRow dr in upCSV.Rows)
{
int? CustomField1 = dr["CustomField1"] as int?;
ObjectParameter getCustomField1 ;
if (CustomField1.HasValue)
{
getCustomField1 = new ObjectParameter("CustomField1", CustomField1);
}
else
{
getCustomField1 = new ObjectParameter("CustomField1", typeof(global::System.Int32));
getCustomField1.Value = DBNull.Value;
}
var results = ordertable.usp_AppUpdateUserData(getCustomField1);
}

The method 'OrderBy' must be called before the method 'Skip' Exception

I was trying to implement the jQgrid using MvcjQgrid and i got this exception.
System.NotSupportedException was unhandled by user code
Message=The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
Though OrdeyBy is used before Skip method why it is generating the exception? How can it be solved?
I encountered the exception in the controller:
public ActionResult GridDataBasic(GridSettings gridSettings)
{
var jobdescription = sm.GetJobDescription(gridSettings);
var totalJobDescription = sm.CountJobDescription(gridSettings);
var jsonData = new
{
total = totalJobDescription / gridSettings.PageSize + 1,
page = gridSettings.PageIndex,
records = totalJobDescription,
rows = (
from j in jobdescription
select new
{
id = j.JobDescriptionID,
cell = new[]
{
j.JobDescriptionID.ToString(),
j.JobTitle,
j.JobType.JobTypeName,
j.JobPriority.JobPriorityName,
j.JobType.Rate.ToString(),
j.CreationDate.ToShortDateString(),
j.JobDeadline.ToShortDateString(),
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
GetJobDescription Method and CountJobDescription Method
public int CountJobDescription(GridSettings gridSettings)
{
var jobdescription = _dataContext.JobDescriptions.AsQueryable();
if (gridSettings.IsSearch)
{
jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
}
return jobdescription.Count();
}
public IQueryable<JobDescription> GetJobDescription(GridSettings gridSettings)
{
var jobdescription = orderJobDescription(_dataContext.JobDescriptions.AsQueryable(), gridSettings.SortColumn, gridSettings.SortOrder);
if (gridSettings.IsSearch)
{
jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
}
return jobdescription.Skip((gridSettings.PageIndex - 1) * gridSettings.PageSize).Take(gridSettings.PageSize);
}
And Finally FilterJobDescription and OrderJobDescription
private static IQueryable<JobDescription> FilterJobDescription(IQueryable<JobDescription> jobdescriptions, Rule rule)
{
if (rule.field == "JobDescriptionID")
{
int result;
if (!int.TryParse(rule.data, out result))
return jobdescriptions;
return jobdescriptions.Where(j => j.JobDescriptionID == Convert.ToInt32(rule.data));
}
// Similar Statements
return jobdescriptions;
}
private IQueryable<JobDescription> orderJobDescription(IQueryable<JobDescription> jobdescriptions, string sortColumn, string sortOrder)
{
if (sortColumn == "JobDescriptionID")
return (sortOrder == "desc") ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID) : jobdescriptions.OrderBy(j => j.JobDescriptionID);
return jobdescriptions;
}
The exception means that you always need a sorted input if you apply Skip, also in the case that the user doesn't click on a column to sort by. I could imagine that no sort column is specified when you open the grid view for the first time before the user can even click on a column header. To catch this case I would suggest to define some default sorting that you want when no other sorting criterion is given, for example:
switch (sortColumn)
{
case "JobDescriptionID":
return (sortOrder == "desc")
? jobdescriptions.OrderByDescending(j => j.JobDescriptionID)
: jobdescriptions.OrderBy(j => j.JobDescriptionID);
case "JobDescriptionTitle":
return (sortOrder == "desc")
? jobdescriptions.OrderByDescending(j => j.JobDescriptionTitle)
: jobdescriptions.OrderBy(j => j.JobDescriptionTitle);
// etc.
default:
return jobdescriptions.OrderBy(j => j.JobDescriptionID);
}
Edit
About your follow-up problems according to your comment: You cannot use ToString() in a LINQ to Entities query. And the next problem would be that you cannot create a string array in a query. I would suggest to load the data from the DB with their native types and then convert afterwards to strings (and to the string array) in memory:
rows = (from j in jobdescription
select new
{
JobDescriptionID = j.JobDescriptionID,
JobTitle = j.JobTitle,
JobTypeName = j.JobType.JobTypeName,
JobPriorityName = j.JobPriority.JobPriorityName,
Rate = j.JobType.Rate,
CreationDate = j.CreationDate,
JobDeadline = j.JobDeadline
})
.AsEnumerable() // DB query runs here, the rest is in memory
.Select(a => new
{
id = a.JobDescriptionID,
cell = new[]
{
a.JobDescriptionID.ToString(),
a.JobTitle,
a.JobTypeName,
a.JobPriorityName,
a.Rate.ToString(),
a.CreationDate.ToShortDateString(),
a.JobDeadline.ToShortDateString()
}
})
.ToArray()
I had the same type of problem after sorting using some code from Adam Anderson that accepted a generic sort string in OrderBy.
After getting this excpetion, i did lots of research and found that very clever fix:
var query = SelectOrders(companyNo, sortExpression);
return Queryable.Skip(query, iStartRow).Take(iPageSize).ToList();
Hope that helps !
SP

H2 Oracle decode function

In H2, I have written a Java decode function. It works with the code:
String sql = "select decode(1.0,2.0,3.0,4.0) from dual ;";
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet resultSet = (ResultSet) stmt.executeQuery();
But the code
String sql = "select 6.0 - decode(1.0,2.0,3.0,4.0) from dual ;";
gives the error:
org.h2.jdbc.JdbcSQLException: Hexadecimal string with odd number of characters: "6.0"; SQL statement:
select 6.0 - decode(1.0,2.0,3.0,4.0) from dual ; [90003-157]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
at org.h2.message.DbException.get(DbException.java:167)
at org.h2.message.DbException.get(DbException.java:144)
at org.h2.util.StringUtils.convertHexToBytes(StringUtils.java:943)
at org.h2.value.Value.convertTo(Value.java:826)
at org.h2.expression.Operation.getValue(Operation.java:108)
at org.h2.command.dml.Select.queryFlat(Select.java:518)
at org.h2.command.dml.Select.queryWithoutCache(Select.java:617)
at org.h2.command.dml.Query.query(Query.java:298)
at org.h2.command.dml.Query.query(Query.java:268)
at org.h2.command.dml.Query.query(Query.java:37)
at org.h2.command.CommandContainer.query(CommandContainer.java:80)
at org.h2.command.Command.executeQuery(Command.java:181)
at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:96)
My decode function is as:
public final static Value decode(Value expression, Value ... paramValues) {
boolean param = true;
boolean hit = false;
Value returnValue = null;
Value defaultValue = null;
// Walk through all parameters, alternately the 'param' and corresponding 'value'.
// If 'param' is equal the expression, then return the next 'value'.
// If no hit, the return the last 'param' value as default value.
for (Value str : paramValues) {
if (param) {
defaultValue = str; // In case this is the last parameter.
// Remember the hit. The next value will be returned.
hit = (MiscUtil.equals(expression, str));
} else {
if (hit) {
returnValue = str;
break; // return str;
}
defaultValue = null;
}
param = ! param;
}
return (returnValue==null) ? defaultValue : returnValue;
}
Is there anything wrong with my decode function?
I have tried to return Object instead of Value in the decode function, and added this code at the end:
Object returnObject=null;
if (returnValue instanceof ValueDecimal) {
returnObject = ((ValueDecimal)returnValue).getBigDecimal();
} else if (returnValue instanceof ValueString) {
returnObject = ((ValueString)returnValue).getString();
} else if (returnValue instanceof ValueDate) {
returnObject = ((ValueDate)returnValue).getDate();
}
return returnValue;
But the I got:
org.h2.jdbc.JdbcSQLException: Data conversion error converting "aced0005737200146a6176612e6d6174682e426967446563696d616c54c71557f981284f0300024900057363616c654c0006696e7456616c7400164c6a6176612f6d6174682f426967496e74656765723b787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200146a6176612e6d6174682e426967496e74656765728cfc9f1fa93bfb1d030006490008626974436f756e744900096269744c656e67746849001366697273744e6f6e7a65726f427974654e756d49000c6c6f776573745365744269744900067369676e756d5b00096d61676e69747564657400025b427871007e0002fffffffffffffffffffffffefffffffe00000001757200025b42acf317f8060854e0020000787000000001287878"; SQL statement:
select 6.0 - cast(decode(1.0,2.0,3.0,4.0) as double) xxx from dual ; [22018-157]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:327)
at org.h2.message.DbException.get(DbException.java:156)
at org.h2.value.Value.convertTo(Value.java:855)
at org.h2.expression.Function.getSimpleValue(Function.java:733)
at org.h2.expression.Function.getValueWithArgs(Function.java:893)
at org.h2.expression.Function.getValue(Function.java:432)
at org.h2.expression.Operation.getValue(Operation.java:113)
at org.h2.expression.Alias.getValue(Alias.java:35)
...
I also did some try with ValueExpression without luck.
Full support for decode in H2 would be the best solution. Is that something you can provide Thomas?
H2 thinks the data type is JAVA_OBJECT, and therefore wants to convert the parameters (6.0 and the result of the decode) to JAVA_OBJECT, which means first convert to a byte array. This fails.
I didn't test it myself, but explicit CAST should work:
select 6.0 - cast(decode(1.0,2.0,3.0,4.0) as double) from dual
It's a bit ugly I know.

Calling System.Linq.Queryable methods using types resolved at runtime

I'm building a LINQ-based query generator.
One of the features is being able to specify an arbitrary server-side projection as part of the query definition. For example:
class CustomerSearch : SearchDefinition<Customer>
{
protected override Expression<Func<Customer, object>> GetProjection()
{
return x => new
{
Name = x.Name,
Agent = x.Agent.Code
Sales = x.Orders.Sum(o => o.Amount)
};
}
}
Since the user must then be able to sort on the projection properties (as opposed to Customer properties), I recreate the expression as a Func<Customer,anonymous type> instead of Func<Customer, object>:
//This is a method on SearchDefinition
IQueryable Transform(IQueryable source)
{
var projection = GetProjection();
var properProjection = Expression.Lambda(projection.Body,
projection.Parameters.Single());
In order to return the projected query, I'd love to be able to do this (which, in fact, works in an almost identical proof of concept):
return Queryable.Select((IQueryable<TRoot>)source, (dynamic)properProjection);
TRoot is the type parameter in SearchDefinition. This results in the following exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
The best overloaded method match for
'System.Linq.Queryable.Select<Customer,object>(System.Linq.IQueryable<Customer>,
System.Linq.Expressions.Expression<System.Func<Customer,object>>)'
has some invalid arguments
at CallSite.Target(Closure , CallSite , Type , IQueryable`1 , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet]
(CallSite site, T0 arg0, T1 arg1, T2 arg2)
at SearchDefinition`1.Transform(IQueryable source) in ...
If you look closely, it's inferring the generic parameters incorrectly: Customer,object instead of Customer,anonymous type, which is the actual type of the properProjection expression (double-checked)
My workaround is using reflection. But with generic arguments, it's a real mess:
var genericSelectMethod = typeof(Queryable).GetMethods().Single(
x => x.Name == "Select" &&
x.GetParameters()[1].ParameterType.GetGenericArguments()[0]
.GetGenericArguments().Length == 2);
var selectMethod = genericSelectMethod.MakeGenericMethod(source.ElementType,
projectionBody.Type);
return (IQueryable)selectMethod.Invoke(null, new object[]{ source, projection });
Does anyone know of a better way?
Update: the reason why dynamic fails is that anonymous types are defined as internal. That's why it worked using a proof-of-concept project, where everything was in the same assembly.
I'm cool with that. I'd still like to find a cleaner way to find the right Queryable.Select overload.
The fix is so simple it hurts:
[assembly: InternalsVisibleTo("My.Search.Lib.Assembly")]
Here's my test as requested. This on a Northwind database and this works fine for me.
static void Main(string[] args)
{
var dc = new NorthwindDataContext();
var source = dc.Categories;
Expression<Func<Category, object>> expr =
c => new
{
c.CategoryID,
c.CategoryName,
};
var oldParameter = expr.Parameters.Single();
var parameter = Expression.Parameter(oldParameter.Type, oldParameter.Name);
var body = expr.Body;
body = RebindParameter(body, oldParameter, parameter);
Console.WriteLine("Parameter Type: {0}", parameter.Type);
Console.WriteLine("Body Type: {0}", body.Type);
var newExpr = Expression.Lambda(body, parameter);
Console.WriteLine("Old Expression Type: {0}", expr.Type);
Console.WriteLine("New Expression Type: {0}", newExpr.Type);
var query = Queryable.Select(source, (dynamic)newExpr);
Console.WriteLine(query);
foreach (var item in query)
{
Console.WriteLine(item);
Console.WriteLine("\t{0}", item.CategoryID.GetType());
Console.WriteLine("\t{0}", item.CategoryName.GetType());
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Console.WriteLine();
}
static Expression RebindParameter(Expression expr, ParameterExpression oldParam, ParameterExpression newParam)
{
switch (expr.NodeType)
{
case ExpressionType.Parameter:
var parameterExpression = expr as ParameterExpression;
return (parameterExpression.Name == oldParam.Name)
? newParam
: parameterExpression;
case ExpressionType.MemberAccess:
var memberExpression = expr as MemberExpression;
return memberExpression.Update(
RebindParameter(memberExpression.Expression, oldParam, newParam));
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
var binaryExpression = expr as BinaryExpression;
return binaryExpression.Update(
RebindParameter(binaryExpression.Left, oldParam, newParam),
binaryExpression.Conversion,
RebindParameter(binaryExpression.Right, oldParam, newParam));
case ExpressionType.New:
var newExpression = expr as NewExpression;
return newExpression.Update(
newExpression.Arguments
.Select(arg => RebindParameter(arg, oldParam, newParam)));
case ExpressionType.Call:
var methodCallExpression = expr as MethodCallExpression;
return methodCallExpression.Update(
RebindParameter(methodCallExpression.Object, oldParam, newParam),
methodCallExpression.Arguments
.Select(arg => RebindParameter(arg, oldParam, newParam)));
default:
return expr;
}
}
Also, dynamic method resolution doesn't really do much for you in this case as there are only two very distinct overloads of Select(). Ultimately you just need to remember that you won't have any static type checking on your results since you don't have any static type information. With that said, this will also work for you (using the above code example):
var query = Queryable.Select(source, expr).Cast<dynamic>();
Console.WriteLine(query);
foreach (var item in query)
{
Console.WriteLine(item);
Console.WriteLine("\t{0}", item.CategoryID.GetType());
Console.WriteLine("\t{0}", item.CategoryName.GetType());
}

Resources