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
};
Related
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.
As the question suggests I want to remove the columns from a select query where in that column are empty.
var query = from a in ...
select new
{
A =(decimal?)null,
B =(decimal?)null,
C = a.Amount1
};
var query2 = from b in ...
select new
{
A = b.Amount2,
B = b.Amount3,
C = (decimal?)null
};
var query3 = query.Concat(query2);
Output:
query3=[0]{A=null, B=null, C=100.00}
[1]{A=100.00, B=50.25, C=null}
Expected Result:
query3=[0]{C=100.00}
[1]{A=100.00, B=50.25}
You can't do this. The result set has to contain items of the same type and even if fields are null they still have to be there.
You could not show them in your UI, but exactly how you do that will depend on the UI.
You can't. A class has a predefined set of fields (not to speak about ExpandoObject which has some compiler tricks going on). This is the same for anonymous type, which you use.
You can't just hide or remove fields which are not filled. What if you iterate over the instances and try to retrieve item.C, which was null and thus removed? That would normally give you a compiler error. How would .NET resolve that?
The only other thing you can do is put in two different types in your list (a list of objects, so untyped), a very bad idea in my opinion. Keep it like this. You could add an indicator which type the row is, to be able to test it easily.
So:
select new
{
Type = "A", // or "B"
A =(decimal?)null,
B =(decimal?)null,
C = a.Amount1
};
A LINQ query typically outputs objects of a common type, so each object has to have the same base type (and the columns associated. The only way to concatenate objects of different types is to cast them to object:
var query = from a in ...
select new
{
C = a.Amount1
};
var query2 = from b in ...
select new
{
A = b.Amount2,
B = b.Amount3,
};
var query3 = query.Cast<object>().Concat(query2.Cast<object>());
but since they're anonymous you'll have to use dynamic to access them since you won;t be able to cast back to the original type, so you'll end up with something like this:
Console.WriteLine(((dynamic)(query3[0])).C);
Console.WriteLine(((dynamic)(query3[1])).A);
or at best:
dynamic list = query3.ToList();
Console.WriteLine(list[0].C);
Console.WriteLine(list[1].A);
but in any case you'll lose compile-time type safety.
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;
is something like the penultimate line here possible? I.E. referring to other properties within the declaration itself?
In my actual code, A and B are set to complex LINQ Enumerables (which is fine) and C could be something like A.Count():
class Thing {
public int A;
public int B;
public int C;
}
Thing myThing = new Thing() {
A = 1,
B = 2,
C = A+B
}
Just trying to find the most efficient way of constructing myThing.
Consider this example:
int A = 0;
int B = 0;
int C = 0;
MyThing myThing = new MyThing() {
A = 1,
B = 2,
C = A + B
}
// myThing.A == 1
// myThing.B == 2
// myThing.C == 0
So, no; it is not possible. Use any of the other answers instead.
Sadly, it's not possible to retrieve a property's value in the object's initializer.
I don't think A and B would be updated before you can reference them to use in C. The solution in my eyes is to simple assign A and B to variables before creating the Object:
var variable1 = 1
var variable2 = 2
Thing myThing = new Thing() {
A = variable1,
B = variable2,
C = variable1+variable2
}
that way you can be sure both variables are changed before you use them for C
Edit: "do I have no choice but to define property C after initialising the object?"
The problem is that A and B aren't initialised yet, so you can't use them to create C. But if you initialise them under another name(variable 1 and variable 2 in the above example) you can then go on to use those values to get C
Object initialiser syntax you're using is just a shortcut for assigning the values, so you could do this:
Thing myThing = new Thing() {
A = 1,
B = 2};
myThing.C =myThing.A + myThing.B;
Properties to the rescue (based on your example)
class Thing {
public IEnumerable<someType> A { get; set; }
public IEnumerable<someType> B { get; set; }
public int C { get { return A.Count(); } }
}
You just need to set A and B, C will come out "on its own" based on the other two. Add null-checks and error handling as needed. In fact, C cannot be set at all in this sample, and it's correct because its value dependes on another property (here it's A).
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();