How to use a parameters value as the property to be selected in a LINQ Query? - asp.net

I am using LINQ-to-Entities and here is my query
public void SomeFunction(string searchField)
{
var data = from a in dx.SomeTable where
a.SomeProperty="270"
select a;
.
.
.
}
Now if I had to use the value of the parameter "searchField" as the property to be selected in the where clause then how do I do it ?
i.e I want to assign the value of the parameter "searchField" to the property I am checking in the where clause.
So ... the value of "SomeProperty" in a.SomeProperty must be the value of "searchField". How to do this ?
PS :
I dont want a.SomeProperty=searchField.
What I want is "SomeProperty" itself to be replaced by the value of "searchField" and then , this has to be checked to see if its equal to 270.

Scottgu posted how to do this a while ago:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

If the caller knows the type of your a (let's say it's MyType), I would suggest that you don't need dynamic LINQ - you can just pass in a predicate function:
public void SomeFunction(Func<MyType, bool> selector)
{
// ...
var data = from a in dx.SomeTable
where selector(a)
select a;
}
// Calling code
SomeFunction(a => a.SomeProperty == "270");
Or if you want to keep the 270 value within SomeFunction, pass in a projection function to pull out SomeProperty :
public void SomeFunction(Func<MyType, string> propertyExtractor)
{
// ...
var data = from a in dx.SomeTable
where propertyExtractor(a) == "270"
select a;
}
// Calling code
SomeFunction(a => a.SomeProperty);
(apologies if this doesn't compile, am currently away from a compiler)

Related

Combine NSArrayController with NSTableview method "objectValueFor"

Can I use NSArrayController for my tableview , and using simultaneously this method : ?
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?
The idea behind:
I do not want to loose the benefits of the arraycontroller ( insert, update, delete ...) but I would like to have control on additional columns to display. The information inside these columns are calculated and formatted; values are coming from the array that the arraycontroller manages (Core Data).
I am afraid this is not possible because controller and tableviewfunction excludes each other ...
Thanks to Willeke, I got it made finally by using a extension for my entity.
extension ImportLog {
// Splits the imported lines into individual words
// For each entity, I split the property "line" .
// Later, in the objc computed property, I pick column number x
var splittedText:[String.SubSequence]{
return(self.line!.split(separator: ";"))
}
// col1
#objc var f1: String {
get {
let theColumn = 0
var text:String = ""
if ( splittedText.count-1 >= theColumn) {
text = String(splittedText[theColumn])
}
return text
}
set {
// no need to set something
}
}
}
The computed property "f1" of the entity can now be bound in the XIB file
by "Table Cell View.objectValue.f1"

My Batis delete query return type not consistent

I am using spring-mybatis for a Delete query
this is how my calls look like
if(mapper.deleteSomething(id))
{
.....
}
And in my mapper i have
<delete id = "deleteSomething">
delete from table where id = #{id}
</delete>
However I noticed that return type is not always true in case of successful deletion. Sometimes it returns true and sometimes false, But the records are always deleted in db.
What am I doing wrong?
Here is changes you need to make.
Change the mapper interface method
public interface yourinterface{
public int deleteSomething(<data type> id)
}
I see in your mapper file there is no parameter type mentioned for input, its better to add
Change if condition
int count =mapper.deleteSomething(id);
if(count>0){
System.out.println("Deleted "+ count +"records");
}else{
System.out.println("Delete failed");
}

Cannot implicitly convert type 'System.Linq.IQueryable to System.Data.Entity.DbSet<>

I receive the following error when I try to run my code. I haven't managed to solve it yet, please Help:
edit: Marked with * where it fails.
>
public IQueryable<Video> GetVideos([QueryString("id")] int? categorieId)
{
var _db = new TeleviziuneAcademicaAspSilverlight.Models.VideoContext();
IQueryable<Video> query = *_db.Videos;*
if (categorieId.HasValue && categorieId > 0)
{
query = query.Where(v => v.CategorieID == categorieId);
}
return query;
Change
IQueryable<Video> query =
to
IQueryable<Appname.Models.Video> query =
The reason for your error is that you have the type Video defined twice and because of using a short type name you accidentally reference not the one Video you should.
Also change it in the method's return value
public IQueryable<Appname.Models.Video> GetVideos( ... )
You seem to have two classes called Video. If you need both, you'll need to project from one to the other before your return statement:
return query.Select(dbVideo => new Appname.Video()
{
Prop1 = dbVideo.Prop1,
Prop2 = dbVideo.Prop2,
// etc.
});
Though you'll probably need to change the return type to an IEnumerable<> if you do that.
If you can just work with Appname.Models.Video, change IQueryable<Video> to IQueryable<Appname.Models.Video> in the method signature and the method body.

SQL statement's placeholders that is not replaced leads to "Cannot update '#columnName'; field not updateable"

I'm writing some code updating database with a SQL statement that has some placeholders . But it doesn't seem to update these placeholders.
I got the following error:
Cannot update '#columnName'; field not updateable
Here is the method:
public void updateDoctorTableField(string columnName, string newValue, string vendorNumber) {
sqlStatement = "update Doctor set #columnName = #newValue where `VENDOR #` = #vendorNumber;";
try {
_command = new OleDbCommand(sqlStatement, _connection);
_command.Parameters.Add("#columnName", OleDbType.WChar).Value = columnName;
_command.Parameters.Add("#newValue", OleDbType.WChar).Value = newValue;
_command.Parameters.Add("#vendorNumber", OleDbType.WChar).Value = vendorNumber;
_command.ExecuteNonQuery();
} catch (Exception ex) {
processExeption(ex);
} finally {
_connection.Close();
}
}
Not all parts of the query are parameterisable.
You can't parametrise the name of the column. This needs to be specified explicitly in your query text.
If this is sent via user input you need to take care against SQL Injection. In fact in any event it would be best to check it against a whitelist of known valid column names.
The reason the language does not allow for parameters for things like table names, column names and such is exactly the same reason why your C# program does not allow for substitution of variables in the code. Basically your question can be rephrased like this in a C# program:
class MyClass
{
int x;
float y;
string z;
void DoSomething(string variableName)
{
this.#variable = ...
}
}
MyCLass my = new MyClass();
my.DoSomething("x"); // expect this to manuipulate my.x
my.DoSomething("y"); // expect this to manuipulate my.y
my.DoSomething("z"); // expect this to manuipulate my.z
This obviously won't compile, because the compiler cannot generate the code. Same for T-SQL: the compiler cannot generate the code to locate the column "#columnName" in your case. And just as in C# you would use reflection to do this kind of tricks, in T-SQL you would use dynamic SQL to achieve the same.
You can (and should) use the QUOTENAME function when building your dynamic SQL to guard against SQL injection.

Accessing the object/row being edited in Dynamic Data

I'm modifying the "Edit.aspx" default page template used by ASP.NET Dynamic Data and adding some additional controls. I know that I can find the type of object being edited by looking at DetailsDataSource.GetTable().EntityType, but how can I see the actual object itself? Also, can I change the properties of the object and tell the data context to submit those changes?
Maybe you have found a solution already, however I'd like to share my expresience on this.
It turned out to be a great pita, but I've managed to obtain the editing row. I had to extract the DetailsDataSource WhereParameters and then create a query in runtime.
The code below works for tables with a single primary key. If you have compound keys, I guess, it will require modifications:
Parameter param = null;
foreach(object item in (DetailsDataSource.WhereParameters[0] as DynamicQueryStringParameter).GetWhereParameters(DetailsDataSource)) {
param = (Parameter)item;
break;
}
IQueryable query = DetailsDataSource.GetTable().GetQuery();
ParameterExpression lambdaArgument = Expression.Parameter(query.ElementType, "");
object paramValue = Convert.ChangeType(param.DefaultValue, param.Type);
Expression compareExpr = Expression.Equal(
Expression.Property(lambdaArgument, param.Name),
Expression.Constant(paramValue)
);
Expression lambda = Expression.Lambda(compareExpr, lambdaArgument);
Expression filteredQuery = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, query.Expression, lambda);
var WANTED = query.Provider.CreateQuery(filteredQuery).Cast<object>().FirstOrDefault<object>();
If it's a DD object you may be able to use FieldTemplateUserControl.FindFieldTemplate(controlId). Then if you need to you can cast it as an ITextControl to manipulate data.
Otherwise, try using this extension method to find the child control:
public static T FindControl<T>(this Control startingControl, string id) where T : Control
{
T found = startingControl.FindControl(id) as T;
if (found == null)
{
found = FindChildControl<T>(startingControl, id);
}
return found;
}
I found another solution, the other ones did not work.
In my case, I've copied Edit.aspx in /CustomPages/Devices/
Where Devices is the name of the table for which I want this custom behaviour.
Add this in Edit.aspx -> Page_Init()
DetailsDataSource.Selected += entityDataSource_Selected;
Add this in Edit.aspx :
protected void entityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
Device device = e.Results.Cast<Device>().First();
// you have the object/row being edited !
}
Just change Device to your own table name.

Resources