I'm trying to build a method that will receive a Linq table, and should return a List<> of values that will be a DropDownList Datasource.
This is what I've got till now:
public static List<Structs.NameValuePair> GenDropDownItens<T>(string ValueField , string TextField ) where T: class
What i don't know how to do is, query the table getting only the fields that are passed ( ValueField, TextField)...
Tks!
Project the result of your LINQ2SQL query into a System.Collections.Generic.KeyValuePair object like so:
ddl.DataSource = DataContext.Table.Select(o => new KeyValuePair<string, string>(o.ID, o.DisplayField));
ddl.DataBind();
You will then want to set the DataValueField and DataTextField attributes on the DropDownList to "Key" and "Value" respectively.
Why not just do something like;
var dropDownValues = dataContext.SomeTable.ToDictionary(
s => s.Name,
s => s.Value
);
foreach(var item in dropDownValues) {
var OptionName = item.Key;
var OptionValue = item.Value
};
Hope this helps, I really don't think you need to create a while method. But if you wanted to I would say have it take a IDictionary object, and convert it from there.
Table.Select( t => t.field1, t.field2 )
Also check out Scott Gutherie's blog series here.
Are you trying to do something like the following with your method
GetDropDownItems("Gates", "LastName") ????
If so, included as part of the SDK samples is a project called DynamicQuery. Using this you can basically create a text version of the query you want. You could do something like
"LastName == 'Gates'"
However, it is just as easy to build the expression tree yourself. The best way to learn what the expressions tree's look like is to use the ExpressionTreeVisualizer VS debugger add in (note this is also another sample contained in the SDK CSharpSamples). It would be something like
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
var expression = Expression.Equals(Expression.Property(parameter, "LastName"), Expression.Constant("Gates")
If "Key" and "Value" are strings that represent the name of the properties you would like to get, and they are known only at runtime... here's your code:
private static Func<T, DictionaryEntry> GetNameValuePairFunc<T>(string valueField, string textField)
{
Func<T, DictionaryEntry> result = (item) =>
{
object key = typeof(T).GetProperty(valueField).GetValue(item, null);
object text = typeof(T).GetProperty(textField).GetValue(item, null);
return new DictionaryEntry(key, text);
};
return result;
}
Related
In C#, I'm going to use lambda expression, I have such a code
var item = dbContext.Products.ToList();
How can i get a property of Product table.
try this
var item = dbContext.Products.FirstOrDefault().Name;
With Lamba expression normally you can access and read information from "list" or in this case, IQueryable objects.
With your code you can access to objects with something like this:
var item = dbContext.Products.FirstOrDefault();
// item may be null if products table is empty
if (item != null)
{
// now you can access at object properties (example)
var data = item.PropertyData;
}
Your question may open others way that including reflection for exploring object without well known class definition...
If you want to get the property for each product with lambda expression, then you should make a lambda expression like x => x.Prop when you do your query
if (dbContext.Products != null){
var list = dbContext.Products.ToList();
var query = list.Select(x => x.Prop //your property will appear here...
}
just I want to ask is it possible to Call function as ToUpper or ToLower() as string for example f.Name.Replace(" ", "_").ToLower()".ToLower()" or "ToUpper" for example if user select convert file name to ToLower() from dropdown list.it will take the value 'ToLower' and added to in of the function and executed the function call
Well, not cleanly. You could use reflection to find the method but you'd have to know the exact type that the function will be applied to since you won't get sophisticated binding like you do at compile-time. Plus you'll be limited to one method signature (in this case, no input parameters and returns a string).
To support any string function with that signature you could use:
string val = f.Name.Replace(" ", "_").ToLower();
string strCommand = "ToUpper";
MethodInfo theMethod = typeof(string).GetMethod(strCommand,new Type[] {});
string result = (string)(theMethod.Invoke(val,null));
But a simple switch seems cleaner and safer here.
The conditional operator (?:) would probably be a better option here
var fileName = f.Name.Replace(" ", "_");
fileName = ddl.SelectedValue == "ToLower" ? fileName.ToLower() : fileName.ToUpper();
Using Reflection for something as trivial as this is pretty unnecessary.
If you know the methods you want to call before, you can register them in a dictionary (key = name of the function or something user friendly, value = function that performs the conversion):
var dict = new Dictionary<string, Func<string, string>>();
dict.Add("Lowercase", x => x.ToLower());
dict.Add("Uppercase", x => x.ToUpper());
You can bind the drop down list to the dictionary (text = Key, value = Value) and perform the conversion as follows (ddl is the name of the DropDownList):
var f = (Func<string, string>)ddl.SelectedValue;
var convStr = f(inputStr);
You can create a defined dictionary of functions, which you can access by name of the action. You will get rid of any conditional statements and of all reflection. Example is given below:
var actions = new Dictionary<string, Func<string, string>>()
{
//keys may have other, human-readable values
{"ToLower", s => s.ToLower()},
{"ToUpper", s => s.ToUpper()}
};
//you will receive this from drop down list, it's the name of the action
var userSelectedOption = "ToUpper";
//string that you want to process
var myString = "some other user input";
//selecting appropriate action and passing myString to it
var transformedString = actions[userSelectedOption](myString);
//prints "SOME OTHER USER INPUT"
Console.WriteLine(transformedString);
Using reflection, you can call a methods using a string:
String ToLower = "ToLower";
String SometString = "This Is My String";
Type stringType = typeof(String);
// Get the overload of ToLower that takes no parameters
MethodInfo method = stringType.GetMethod(ToLower, System.Type.EmptyTypes);
// Invoke the method with no parameters
String newString = (String)method.Invoke(SometString, null);
MessageBox.Show(newString);
If I have understood your question correctly, you want to call a method based on a string.
You can use reflection, which is a topic in and of itself, but to get you started you can do something like:
MethodInfo chosenMethod = typeof(string).GetMethod(methodName, Types.EmptyTypes);
chosenMethod.Invoke(stringToModify, new object[]{});
But if it is a very limited set of functions you want to expose, you should just do a switch statement over the user input:
switch(methodName)
{
case "ToLower":
stringToModify.ToLower();
break;
...
You can use a simple switch statement:
switch (value) // Assuming value is of type SomeEnum
{
case SomeEnum.ToLower:
return f.ToLower()
case SomeEnum.ToUpper:
return f.ToUpper();
default:
//Do the Default
break;
}
This is how you parse what you get from the UI:
public static T ParseEnum<T>( string value )
{
return (T) Enum.Parse( typeof( T ), value, true );
}
Perhaps you might need to avoid limitations is sort of a Runtime intepreter of C#, like eval() function in JavaScript, which is not easily nor trivial to implement, but there is a good library out there called C# Eval ( http://csharp-eval.com/Download.php ) that uses Reflection internally of course. It is heavier but more effective for this, or even for much more complex escenarios.
You might use it in this way for example:
class Person
{
public string Name;
public string Process(string expression)
{
return CsEval.Eval(this, expression);
}
}
And then might call it:
var f = new Person();
f.Name = "John";
f.Name = f.Process("Name.Replace(" ", "_").ToLower()");
Of course this is just an example of how it evaluate what is in the string, as you can see you just need to pass a "context" where the expression is going to mean something, which in this case is the current class ("this").
I'm filling a drop-down list using the following:
var columnNames = db.Mapping.MappingSource.GetModel(typeof(StaffDirectoryDataContext))
.GetMetaType(typeof(Person)).DataMembers;
I'm then converting that to a List<String> to populate a drop down list.
I then want to be able to get a set of results based on the user's selection. For example, if they select "First name" from the drop down list and type "Bob" into the text box I want to run a LINQ query where first name = bob.
I'm probably being thick but I can't find a way! Pseudo code would be...
var q = from x in dc.Persons
where x.[selected column name] == [textbox value]
select x;
Can anybody help? Essentially I have the column name as a String value, and I can't figure out how to tell the LINQ query that that's the column to filter on!
Could do this in ADO.NET with my eyes closed, but determined to use LINQ all the way!!
Thanks in advance.
David Buchanan has posted a solution for this problem using reflection :
msdn forum
I'm not sure you can do this dynamically, but you can do it conditionally. Something like this:
switch(selected column name)
{
case "student_no":
q = q.where(p=>p.StudentNo == value);
break;
case "student_id":
q = q.where(p=>p.StudentId == value);
break;
}
You can iterate through your columns and keep building the wheres. The SQL won't be executed as long as none of the calls force the IQueryable to execute.
I think expression trees are the right way to do this, but I don't know them very well so I'm going to give you the alternate way I would have done this if I didn't feel like learning expression tree building..
public interface IFilter { IEnumerable RetreiveFilter(string filterValue); }
public class FirstNameFilter : IFilter
{
private const string FILTER_TYPE_NAME = "First Name";
public IEnumerable RetreiveFilter(string filterValue)
{
return _myData.Where(person => person.FirstName = filtervalue);
}
public override string ToString()
{
return FILTER_TYPE_NAME;
}
}
Create a class like this for each filter type, and then fill your dropdown with these filters, and when they type info into the filter text, it will execute against the ((IFilter)filterDropDown.SelectedItem).RetreiverFilter(filterTextBox.Text);
I have seen the reverse of this question quite a few times, but have not seen how to do what I would like.
Suppose I have the following code:
var myNewData = from t in someOtherData
select new
{
fieldName = t.Whatever,
fieldName2 = t.SomeOtherWhatever
};
If I wish to data bind to this class, my column definition would have to include hard-coded strings like "fieldName" and "fieldName2".
Is there any way to call reflection or something else so that I can do something equivelent to the code below (I know the code below is not valid, but am looking for a valid solution).
string columnName = GetPropertyName(myNewData[0].fieldName);
My goal is that if the variable name changes on the anonymous class, a compile-time error would come up until all references were fixed, unlike the current data binding which relies on strings that are not checked until runtime.
Any help would be appreciated.
string columnName = GetPropertyName(() => myNewData[0].fieldName);
// ...
public static string GetPropertyName<T>(Expression<Func<T>> expr)
{
// error checking etc removed for brevity
MemberExpression body = (MemberExpression)expr.Body;
return body.Member.Name;
}
You get your property names like this:
using System.Reflection;
var myNewData = from t in someOtherData
select new
{
fieldName = t.Whatever,
fieldName2 = t.SomeOtherWhatever
};
foreach (PropertyInfo pinfo in myNewData.FirstOrDefault()
.GetType().GetProperties())
{
string name = pinfo.Name;
}
// or if you need all strings in a list just use:
List<string> propertyNames = myNewData.FirstOrDefault()
.GetType().GetProperties().Select(x => x.Name).ToList();
Hi this seems like it should work,
from something in collectionofsomestuff
select new SelectListItem(){Text = something.Name, Value = something.SomeGuid.ToString(), Selected = false};
When I try to do this it doesn't work give me error
LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.
Is there a workaround?
Not all CLR methods can be used with Linq-to-Entities. ToString() seems to be one of them.
Take a look at CLR Method to Canonical Function Mapping.
Maybe try setting the GUID to a string variable explicitly, outside of Linq.
string myGuid = SomeGuid.ToString();
from something in collectionofsomestuff
select new SelectListItem(){Text = Name, Value = myGuid, Selected = false};
You can get the records in the db,and then turn them to a list or a array use ToList() or ToArray().Then use the object.
For example(it is LINQ to Entities ):
var list = collectionofsomestuff.select(c => c).ToList();
from something in list
select new SelectListItem(){Text = something.Name, Value = something.SomeGuid.ToString(), Selected = false};
I don't speak Linq query expressions too well, but the following should do the trick:
collectionofsomestuff //here it's LinqToEntities
.Select(something=>new{something.Name,something.SomeGuid})
.ToArray() //From here on it's LinqToObjects
.Select(s=>new SelectListItem()
{
Text = s.Name,
Value = s.SomeGuid.ToString(),
Selected = false
})
I ended up doing a foreach like so
List<SelectListItem> list = new List<SelectListItem>();
foreach (SomeThing something in collectionofsomestuff)
{
list.Add(new SelectListItem(){Text = something.Name,Selected = false,Value = something.SomeGuid.ToString()});
}
this is the only way I could get it to work..it wasn't what i was hoping to do tough..
Create a constructor for SelectListItem that accepts your Value as a Guid and ToString it there. Now call your query like so:
from something in collectionofsomestuff select new SelectListItem(something.Name, something.SomeGuid, false);
I had the same problem, and I ended up changing my object's definition to get around the problem. It's a complete hack, but it allows me to populate the data straight from the query:
[DataContract]
public class DeviceInfo
{
public Guid DeviceGuid
{
set
{
DeviceID = value.ToString();
}
}
[DataMember]
public string DeviceID { get; set; }
}
And the query works as designed because it has something else doing the conversion for it:
devices.AddRange(from d in ae.UserDevices
select new DeviceInfo
{
DeviceGuid = d.DeviceID
}
It makes the object a little messier, but makes dealing with the Guid in the query so much easier.