Return partial linq query from method - how to declare return type - c#

I have a linq query written in method syntax. I need to create a very similar method with just some changes to the final Select.
Is it possible to return the partial Linq query from a method so I dont duplicate the code? The issue I have is finding the "Type" of the query to mark the method with.
If I use query.GetType(), it returns (cut down version) :
SubSonic.Linq.Structure.Query`1[<>f__AnonymousType18`6[advert,client]]
I tried to create a return type:
SubSonic.Linq.Structure.Query<advert, client> query = new SubSonic.Linq.Structure.Query<advert, client>();
However I receive the error:
Error 20 Using the generic type 'SubSonic.Linq.Structure.Query<T>' requires '1' type arguments
So I guess I am asking how to declare a return type that is a Subsonic Query containing an anonymous type containing a number of objects? (2 in my example)
Please excuse my simple example:
eg:
internal ????? GetQueryBody(string param1, string param2){
/* buld the linq query here */
}
internal List<Booking> GetSearchResultsOne(string param1, string param2){
var query = this.GetQueryBody(string param1, string param2);
var res = query.Select( db => new Booking { /*fields */).ToList();
return res;
}
internal List<BookingData> GetSearchResultsTwo(string param1, string param2){
var query = this.GetQueryBody(string param1, string param2);
var res = query.Select( db => new BookingData { /*fields*/).ToList();
return res;
}
Thank you for your time,
Yohimbo

Use IEnumerable<T> to return a query.
About the anonymous type: If a type is anonymous, how should another methode know about it? Read more here. To solve the problem, give your anonymous type a name by creating a class.
If you only want to return two types you could also return a tuple: Then T is Tuple<advert,client>. You can create a tuple by
var t = new Tuple<advert,client>(client, advert);

Answer 1: You can't do it because Booking and BookingData are different types so the expression trees are different.
Answer 2: Assuming you can find a common base class, there are two approaches to your question.
The 'type' of what a Linq Query acts on is actually an Expression<TDelegate>. You can construct Expression trees and store them and manipulate them, and then use them where needed.
The 'argument' for your final Select() is actually an Expression<Func<TSource, TResult>>. You can use any function in that location as long as it conforms to that delegate.
In other words, you can store the entire pre-formed expression trees from the top, or you can store one tree and substitute the bit at the bottom. There isn't enough in your sample for me to write the code, and you still have to resolve that fatal flaw.

Related

Abstracting out queries to the Azure Table Storage using Expressions

I'm creating a class to perform CRUD functionality with Azure Table Storage.
I'm using generic types in this.
I have the following method, which i'm trying to pass in an expression to get used in the TableQuery, but am having some issues.
The line TableQuery<T> query = new TableQuery<T>().Where<T>(criteria); won't compile, and gives me the message
Cannot implicitly convert type 'System.Linq.IQueryable<T>'
to 'Microsoft.WindowsAzure.Storage.Table.TableQuery<T>'.
An explicit conversion exists (are you missing a cast?)
I understand the message and know it's telling me i'm missing a cast, though I'm unsure how to code it correctly.
My full method is:
public List<T> GetSome<T>(Expression<Func<T, bool>> criteria) where T : ITableEntity, new()
{
TableQuery<T> query = new TableQuery<T>().Where<T>(criteria); // <---- This line isn't working
List<T> results = table.ExecuteQuery<T>(query).ToList<T>();
return results;
}
Ok, so I figured it out - how i can pass in a lambda expression for Azure Table Storage to use.
I changed my method to the following:
public List<T> GetSome<T>(Expression<Func<T, bool>> criteria) where T : ITableEntity, new()
{
// table, in this case, is my `CloudTable` instance
List<T> results = table.CreateQuery<T>().Where(criteria).ToList();
return results;
}
I can now pass in an expression. For example, to search against a DynamicTableEntity I can use:
// my table storage class
TableStorage ts = new TableStorage("ContactData");
// search with expression
List<DynamicTableEntity> results = ts.GetSome<DynamicTableEntity>(t => t.Properties["FirstName"].StringValue == "Darren");
If this is something you wouldn't/shouldn't do against an Azure Table Store, please do let me know.
In the meantime, this is how I have met the requirement.
The error is because the value returned by the extension method Where is of type IQueryable<T>, but you're assigning to a variable of type TableQuery<T> and there is no implicitly valid type conversion between these types.

How to define anonymous method types to build dynamic queries with LINQ?

I'm busy with a LINQ to SQL project that basically creates multiple threads for each entity type in my database, which constantly queries information from the DB in a thread.
Here's a pseudo example:
streamer.DefineDataExpression<Contacts>(x => x.FirstName == "Bob");
while(true)
{
List<Contacts> MyContactsResult = streamer.ResultList;
// do whatever with MyContactsResult
}
The above code doesn't exist, but this is what I have so far for the 'streamer' class (it obviously doesn't work, but you can see what I'm trying to achieve above):
public void DefineExpression(System.Linq.Expressions.Expression<System.Func<T, bool>> expression)
{
using (var db = new LINQDataContext())
{
ResultList = db.GetTable<T>().Where(expression);
}
}
How do I go about creating a method like 'DefineExpression' that will allow me to query a LINQ type dynamically?
Why not use the Dynamic LINQ provider, as mentioned by Scott Guthrie. I think that would give you everything you are looking for, because you can define the query as a string. Therefore, you can more easily build a string representation of your query, and execute on the fly.

Storing LINQ queries as variables/constants?

Say I have a LINQ-to-XML query that generates an anonymous type like this:
var aQuery =
(from a in document.Root.Elements("items")
select new {
id = a.Attribute("id").Value,
type = a.Attribute("type").Value,
modified = a.Attribute("modified").Value
});
if there a way to store that query expression in a variable or constant and then execute at runtime? The basic idea is that I have a bunch of these expressions and it would be handy if they could all be defined in one place and then invoked dynamically thru a single method where I just need to pass in the XML document and which expression to use. Thanks.
You could define them as methods quite easily, though you'd forfit the right to use anonymous types.
public static IQueryable<Item> GetItemsFromXml(XDocument document)
{
return (from a in document.Root.Elements("items")
select new Item
{
Id = a.Attribute("id").Value,
Type = a.Attribute("type").Value,
Modified = a.Attribute("modified").Value
});
}
Having said that, patterns like the repository pattern are used to wrap the whole process of accessing data.

Executing DynamicExpression with unknown types

If anyone is very familar with the Linq.Dynamic namespace I could use some help -- couldn't find any indepth resources on the internet.
Basically I'm using DynamicExpression.ParseLambda to create an expression where the type is not known at compile time,
public Expression GetExpression(Type t, List<QueryFilter> filters)
{
// pseudo code
// extracts a string representation of the query as 'expressionString'
return DynamicExpression.ParseLambda(t, typeof(Boolean), expressionString, values);
}
Where a QueryFilter is:
public class QueryFilter
{
string propertyName;
ExpressionType operationType;
object value;
}
Which represents a simple binary function like "Age > 15" or something.
This is how the 'GetExpression' function works, it takes 2 types -- one that is the input type and one that is the output type, and ultimately generates what would normally be created with a Func delegate. It also takes a string that represents the query and a params object[] of values, which are 'expressionString' and 'values' above, respectively.
However I am having trouble executing the dynamic expression in LINQ-to-SQL, using a DataContext generated from SqlMetal (.dbmc file).
DatabaseContext db = new DatabaseContext(connectionString);
var filter = DynamicExpressionBuilder.
GetExpression(typeof(SysEventLogT), sysEventFilters)
var query = db.SysEventLogT.Where(filter);
Produces the following error,
System.Data.Linq.Table<DBReporting.Linq.Data.SysEventLogT>
does not contain a definition for 'Where' and the best extension method overload
System.Linq.Dynamic.DynamicQueryable.Where<T>(System.Linq.IQueryable<T>, string, params object[])
has some invalid arguments.
I know that my DataContext instance actually treats the sql tables as properties...do I need to reflect with GetProperty() somehow for this to work? Or perhaps I need to create another .Where extension?
Your GetExpression is returning an Expression type - the DynamicQueryable.Where method, when used as an extension method, expects a string as the first parameter.
You need your call to Where to look like this:
var query = db.SysEventLogT.Where("Age > #0", 15);
Also, you could try the following, just to be explicit:
var query = db.SysEventLogT.AsQueryable().Where("Age > #0", 15);
Note that if easier, you can build a sting containing the full filter and not use the params object[] parameter at all:
var query = db.SysEventLogT.AsQueryable().Where("Age > 15");

How to return Anonymous Type while using Linq [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
LINQ to SQL: Return anonymous type?
Do any one know how to return an anonymous type. I am using Linq where i need to return the following code
private <What's the return type to be provided here> SampleLinq(Int32 Num)
{
var query = (from dept in obj.DeptTable where dept.Id == Num select new { dept.DeptName, dept.DeptId });
return (query)
}
Sorry to say but you cannot return anonymous type out side the scope of method.
This is the alternate way to get anonmous type
// Method that returns anonymous type as object
object ReturnAnonymous()
{
return new { City="Prague", Name="Tomas" };
}
// Application entry-point
void Main()
{
// Get instance of anonymous type with 'City' and 'Name' properties
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 'City' and 'Name' properties
var typed = Cast(o, new { City="", Name="" });
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 it only for types in one assembly (two anonymous types from two different assemblies will be internally compiled to two different types that can't be converted using this trick).
Return Dynamic type:
public static dynamic getCustomer()
{
.....
var x = from c in customers
select new {Fname = c.FirstName};
return x;
}
static void Main(string[] args)
{
dynamic x = getCustomer();
Console.WriteLine(Enumerable.First(x).Fname);
Console.ReadKey();
}
you can't do that. that is why it is called anonymous. It doesn't have a name. But you always can cast it to object
Well, you can't actually do that, but here's a hack on this.
private object SampleLinq(Int32 Num)
{
return (from dept in obj.DeptTable where dept.Id == Num select new { dept.DeptName, dept.DeptId });
}
You can't return an Anonymous Type from a method.
You can create a simple Class to wrap the Anonymous Type, but you still need a Class (or cast to object).
Keep in mind, though, that if you cast to object there's no way to cast back. You'll need reflection to read any data.
The answers you see from the hack is a lot of work just to get an anonymous type through a method boundary. You shouldn't be doing this. If you need to pass something back from a method, you should be passing concrete types.
It depends what you looking to do with the return vale.
If your going to bind it in the UI
you can just rerun
IEnumerable or IQueryable.
If your going to use reflection on the return value just return type object
If your using c# 4.0 you can return a
dynamic type
If your using EF or Linq to SQL to further join a query comprised of your anonymous type you
can make a concrete class instead and
use the concrete placeholder
technique. For more details on this
technique I can give some assistance.
As others have mentioned though, you should really question whether returning an anonymous type form a method is the best way to solve the problem at hand. In general there is usually a better more pattern based approach that may require a bit more coding up front but may resulting in a more elegant design. This being said, I do believe there are legitimate cases such as with data binding where returning anonymous type instances can be perfectly acceptable.
UPDATE:
Just an interested tidbit I wanted to share in case those reading are not aware. Anonymous types are unique per their property names and types so lets say you have method A and method B in in both you create an anonymous type that has a single string typed property called Name by doing something like be code below.
public object A()
{
return new { Name = "Cid" }
}
public object B()
{
return new { Name = "Galuf" }
}
public void Test()
{
System.Diagnostics.Trace.Assert(A().GetType() == B().GetType());
}
Now even though this type is defined in two separate places the compiler only creates only creates a single shared type because they both have the same set of properties as defined by the property types and property names. In this respect the properties can be thought of as sort of a signature for the anonymous type. Using this knowledge there are different techniques that can be used for introspection into anonymous type instances that have been cast to object or deferred using the dynamic keyword. There are also nifty ways to work with anonymous types by using generic methods just as Linq does with methods in the static Enumerable and Queryable classes. This way you can do things like create a new instance of any given anonymous type and without using reflection. The trick is though that you have to use an instance of the anonymous type to pass to methods in order to have the type be inferred by the generic method. If anybody is interested in these topics further as they apply to the original posters question, leave a comment and I can try to clarify some of these techniques.

Categories

Resources