How to get the Id of the selectedvalue? - c#

I have DropDownList with the following values:
ddl.SelectedValue = { Id = 234, Name = "ABC Name" }
How can I get the value of the Id?
I use WinForms and RadDropDownList

Try this one:
public int GetId(object obj)
{
var anon = new { Id = 0, Name = string.Empty };
var obj2 = MakeSameType(obj, anon);
return obj2.Id;
}
public static T MakeSameType<T>(object obj, T anonymous)
{
return (T)obj;
}
use it like:
int id = GetId(ddl.SelectedValue);
If it works, it is thanks to how the equivalent anonymous types are "condensed" in single types by the C# compiler.
Note that this solution is as brittle as you can have
If you add/remove/rename a property of the anonymous type, the GetId will break (you'll have to keep the var anon = new {...} perfectly aligned). If you move the method that creates the collection of anonymous types to another assembly it will break too (because only anonymous types inside the same assembly are "unified" by the compiler).
In general you shouldn't have anonymous types that "escape" a method. An anonymous type should remain in the method that it is defined. Assigning it directly as the DataSource of a control is asking for problems.
If you feel lazy and don't want to create a type for a key-value, use the Tuple:
var tuple = Tuple.Create(something, somethingelse, somethingstillelse);
var value1 = tuple.Item1;
var value2 = tuple.Item2;
var value3 = tuple.Item3;
and so on.

As your are using anonymous types, it gets little complicated. But, you can cast SelectedValue to dynamic, and exstract 'Id' from there:
dynamic selectedValue = ddl.SelectedValue;
int id = selectedValue.Id;
But i would recommend to declare your own class or struct for such cases.

I have changed the LINQ query
from:
var query = (from q in tableq where ...
select new {Id = q.Id, Name = q.Name});
to:
var query = (from q in tableq where ...
select q);
... and then change it to:
table1.Id = (ddl.SelectedValue as tableq).Id == null ? table1.Id : (ddl.SelectedValue as tableq).Id;

Related

use linq to query dynamic object

I dynamically set the type of an object
Then I want to query that object
int id = 123;
dynamic b =
Convert.ChangeType(dataToCompareTo, Type.GetType(tableName));
var values = (from item in (b)
where item.Id == id
select item).FirstOrDefault();
Linq will not allow me to do this ("query expressions with source type of dynamic [..] are not allowed"). I do not know the object type before runtime.
dynamic is the wrong thing to use here. ChangeType has a return type of object. It is not possible for the compiler to know at compile time what the type will be. If you define b as var the compiler will consider b to be an object and know nothing more about it.
Your LINQ expression seems to be expecting a particular type that implements IEnumerable and perhaps even an IEnumerable<SomeType>. In which case you would have to cast it to those types:
int id = 123;
var b =
Convert.ChangeType(dataToCompareTo, Type.GetType(tableName));
IEnumerable<SomeType> c = b as IEnumerable<SomeType>;
if (c == null)
{
///this is where you handle the objects that aren't what you need them to be for the linq expression below
}
else
{
var values = (from item in (c)
where item.Id == id
select item).FirstOrDefault();
}
If you want to use dynamic - you can do it here. Suppose you know that your b variable is list of some type which has Id property but you don't know which, and for whatever reason cannot use interface:
public class SomethingWithId {
public int Id { get; set; }
}
// you have no idea what that is at runtime
object something = new List<SomethingWithId>() {new SomethingWithId() {Id = id}};
Then you can use dynamic like this:
object something = new List<SomethingWithId>() {new SomethingWithId() {Id = id}};
// cast to `IEnumerable<dynamic>`, this will always compile
// but of course might fail at runtime, as always with dynamic
// in your case that is (IEnumerable<dynamic>) Convert.ChangeType(dataToCompareTo, Type.GetType(tableName));
var b = (IEnumerable<dynamic>) something;
// run your query
var values = (from item in b
where item.Id == id
select item).FirstOrDefault();
That said - don't get used to do such things in C# - it's strongly typed languge and you should not ignore benefits provided by that.

linq to sql select new keyword and assign column alias name

i wants to assign column alias to another column in linq to sql select new keyword my code is
var query=from d in db.tblAttributeDatas
select new
{
a=d.strValue,
b=a
};
but compiler give me error.
can not resolved symbol a
.
You cannot use alias that way.
You have to do it using let this way:
var query=from d in db.tblAttributeDatas
let str = d.strValue // hold value here
select new
{
a=str, // now assign here
b=str
};
Basically, you can't do this because of the nature of object initializers (which is: initializing objects using the object literal notation { ... }).
This simple line of code...
var x = new { a = 1, b = 2 };
...is executed in IL code as...
<>f__AnonymousType0<System.Int32,System.Int32>..ctor
So you see that the anonymous type is created having a two-parameter constructor. Suppose this constructor would be visible as...
class X
{
public X(int a, int b) { }
}
It's obvious you can't call this constructor by
var x = new X(1, a);
You must supply two values. One constructor argument can't "borrow" the value of the other argument.
assign the same value to b .. there is no harm..
var query = from d in db.tblAttributeDatas
select new
{
a = d.strValue,
b = d.strValue
};

Dynamic LINQ: Specifying class name in new clause

With Dynamic LINQ, what changes need to be done to have fields of the given class?
For example, how can the following C# query be reproduced in DLinq:
var carsPartial = cars.Select(c => new {c.year, c.name, make = new maker() {name = c.make.name} }).ToList();
I have applied the changes mentioned in this answer https://stackoverflow.com/a/1468357/288747 to allow the return type to be the calling type rather than an anonymous type.
With the class definition is as follows (if it helps):
class car
{
public int vid;
public int odo;
public int year;
public string name;
public maker make;
}
class maker
{
public string name;
public int firstYear;
}
The following doesn't work (but I think is close, but still doesn't work as I don't have the changes necessary to the dynamic linq library, which is what I need):
var carsPartial = cars.Select("new(name, year, new maker() {name = make.name})").ToList();
But it fails at the new maker() { (as expected).
I'm sure I need to change the DynamicLibrary.cs to get this working and could do with some direction on how to alter it to achieve this.
UPDATE: I have turned my answer into a little bit more extensive blog post.
I have not really ever used Dynamic Linq library, but I have taken a look at the DynamicLibrary.cs code and the change to support generating type classes provided in another stackoverflow question you provided link to in your question. Analyzing them all, it seems that the nested new-s should work out of the box in your configuration.
However, it seems your query is not the correct Dynamic Linq's language query. Note, that the query string for DLinq is not equivalent to C# and has its own grammar.
The query should read out, I believe, the following:
var carsPartial = cars.Select("new(name, year, new maker(make.name as name) as make)").ToList();
EDIT:
Rereading this stackoverflow question more carefully, I realizes, that it actually does not extend the Dynamic Linq's language with the possibility for creating new strong-typed classes. They just put the result to the class specified as a generic parameter of Select() instead of specifying it in the query string.
To obtain what you need you will need to revert their changes (get generic DLinq) and apply my changes, I have just verified to work:
Locate the ParseNew method of ExpressionParser class and change it to the following:
Expression ParseNew() {
NextToken();
bool anonymous = true;
Type class_type = null;
if (token.id == TokenId.Identifier)
{
anonymous = false;
StringBuilder full_type_name = new StringBuilder(GetIdentifier());
NextToken();
while (token.id == TokenId.Dot)
{
NextToken();
ValidateToken(TokenId.Identifier, Res.IdentifierExpected);
full_type_name.Append(".");
full_type_name.Append(GetIdentifier());
NextToken();
}
class_type = Type.GetType(full_type_name.ToString(), false);
if (class_type == null)
throw ParseError(Res.TypeNotFound, full_type_name.ToString());
}
ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
NextToken();
List<DynamicProperty> properties = new List<DynamicProperty>();
List<Expression> expressions = new List<Expression>();
while (true) {
int exprPos = token.pos;
Expression expr = ParseExpression();
string propName;
if (TokenIdentifierIs("as")) {
NextToken();
propName = GetIdentifier();
NextToken();
}
else {
MemberExpression me = expr as MemberExpression;
if (me == null) throw ParseError(exprPos, Res.MissingAsClause);
propName = me.Member.Name;
}
expressions.Add(expr);
properties.Add(new DynamicProperty(propName, expr.Type));
if (token.id != TokenId.Comma) break;
NextToken();
}
ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
NextToken();
Type type = anonymous ? DynamicExpression.CreateClass(properties) : class_type;
MemberBinding[] bindings = new MemberBinding[properties.Count];
for (int i = 0; i < bindings.Length; i++)
bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
return Expression.MemberInit(Expression.New(type), bindings);
}
Then, find the class Res and add the following error message:
public const string TypeNotFound = "Type {0} not found";
Et voilĂ , you will be able to construct queries like:
var carsPartial = cars.Select("new(name, year, (new your_namespace.maker(make.name as name)) as make)").ToList();
Make sure, you include the full type name including the whole namespace+class path.
To explain my change, it just checks if there is some identifier between new and opening parenthesis (see the added "if" at the begging). If so we parse full dot-separated class name and try to get its Type through Type.GetType instead of constructing own class in case of anonymous news.
If I've understood you correctly you want to make a plain anonymous class that contains fields from both class car and class maker. If it's the case you can just provide new names in that class, something like the following:
var carsPartial = cars.Select(c => new { year = c.year, name = c.name, make_name = c.make.name });
Or even provide names only to conflicting fields:
var carsPartial = cars.Select(c => new { c.year, c.name, make_name = c.make.name });

How to return Generic.List<Anonymoustype> from a function in C#

ASP.NET 3.5 C#
I am joining two tables using Linq.
Table names are MapAssets and ExitPoint.
In Database they are related with 'has a relationship'
I am writing a function in my BLL to return the joined table
public List<ExitPoints> GetExitPointDetailsByProjectID(int iProjectID)
{
ctx = new CoreDBDataContext();
var exitPointDetails = from ma in ctx.MapAssets
join ep in ctx.ExitPoints
on ma.MapAssetID equals ep.MapAssetID
where ma.ProjectID == iProjectID
select new
{
//would like to have data from both tables here
ctx.MapAssets,
ctx.ExitPoints
};
return exitPointDetails.ToList();
}
This obviuosly doesn't work. And I dont know what to return at all.
All constraint I have for the return is to be able to be bound to a gridview.
is this the correct way? Or else whats the correct way?
You can't, or better, the only way is to return them boxed in a List of object, but this hugely complicates things, because you can't cast them to any type (of course it's anonymous) and you can only access their properties through reflection....
In cases like that, I'd highly suggest you to create a custom class.
EDIT:
On a side note...
If you were using .net 4, things would be easier because you could returns dynamic Type instead of object (look at this link to see dynamic's simplifications), but I'd prefer to create a custom class anyway.
Have a look at how to return anonymous types from Method.
http://forums.asp.net/t/1387455.aspx.
Copying the code from the link.
object ReturnAnonymous()
{
return new { Name="Faisal", City="Chakwal" };
}
// Application entry-point
void Main()
{
object o = ReturnAnonymous();
// This call to 'Cast' method converts first parameter (object) to the
// same type as the type of second parameter - which is in this case
// anonymous type with 'Name' and 'City' properties
var typed = Cast(o, new { Name="", City="" });
Console.WriteLine("Name={0}, City={1}", typed.Name, typed.City);
}
// Cast method - thanks to type inference when calling methods it
// is possible to cast object to type without knowing the type name
T Cast<T>(object obj, T type)
{
return (T)obj;
}
You can use the method mentioned below to return List and
List<object> lstAnonymousTypes = GetExitPointDetailsByProjectID(1);
foreach(object o in lstAnonymousTypes)
{
//Change it accordingly
var typed = Cast(o, new { new MapAssets() , new ExitPoints() });
}
Hope this helps not tried.
You can't return an anonymous type, you can only use an anonymous type in the scope of the method it's in. You could need to create a new class with MapAssets/ExitPoints properties and select a new instance of that class.
You are trying to return List ExitPoints and List of MapAssets which is not possible because you are getting the output from both tables ie ExitPoints and MapAssets. And it is also not possible to return an anonymous type. So in order to retrun the query create a class name ExMapClass with properties that you need as output of the queries. Now after executing the linq query which you have written iterate it ie
create list of newly created class
list newclass = new list ();
foreach( var result in ctx )
{
instantiate the created class
obj.Property1 = var.MapAssets;
obj.Property2 = var.ExitPoints;
newclass.add(obj);
}
now retrun the list of newlycreated class.
hope you got it.
Do you have to bind to this object after you've created it? If not then you can create an "persistent AnonymousType" class that stores the values in a dictionary and returns the property values with a method like:
string lastName AnonType.GetValue<string>("LastName");
int age AnonType.GetValue<int>("Age");
Here is a link to an excellent example. The author also has an example where he creates the "AnonymousType" from a datatable.
I have worked on a variation of this where I provide the ability to query a list of "AnonymousType" with the following syntax:
// Here's the query
var dept13 = anonAgents.AsQueryable()
.Where(x => x.Has("Department", Compare.Equal, 13);
// Here is how the List is constructed
private static AnonymousType ProvisionAgent(string name, int department)
{
return AnonymousType.Create(new
{
Name = name,
Department = department
});
}
private List<AnonymousType> CreateAnonAgentList()
{
var anonAgents = new List<AnonymousType>();
// Dave and Cal are in Department 13
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Dan Jacobs", 13, 44)));
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Calvin Jones", 13, 60)));
// Leasing = Dept 45
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Stanley Schmidt", 45, 36)));
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Jeff Piper", 45, 32)));
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Stewart Blum", 45, 41)));
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Stuart Green", 45, 38)));
// HR = Dept 21
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Brian Perth", 21, 25)));
anonAgents.Add(AnonymousType.Create(CreateAgentAnonType("Katherine McDonnel", 21, 23)));
return anonAgents;
}
Just use and ArrayList
public static ArrayList GetMembersItems(string ProjectGuid)
{
ArrayList items = new ArrayList();
items.AddRange(yourVariable
.Where(p => p.yourProperty == something)
.ToList());
return items;
}
wont this work ?
ctx = new CoreDBDataContext();
var exitPointDetails = from ma in ctx.MapAssets
join ep in ctx.ExitPoints
on ma.MapAssetID equals ep.MapAssetID
where ma.ProjectID == iProjectID
select Tuple.Create(ma, ep);
return exitPointDetails.ToList();

LINQ Guid toString()

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.

Categories

Resources