tags:

views:

105

answers:

3

I would like to find out if anyone has existing work surrounding formatting an IQueryable instance back into a LINQ C# syntax inside a string. It'd be a nice-to-have feature for an internal LINQ-to-SQL auditing framework I'm building. Once my framework gets the IQueryable instance from a data repository method, I'd like to output something like:

This LINQ query:

from ce in db.EiClassEnrollment
join c in db.EiCourse on ce.CourseID equals c.CourseID
join cl in db.EiClass on ce.ClassID equals cl.ClassID
join t in db.EiTerm on ce.TermID equals t.TermID
join st in db.EiStaff on cl.Instructor equals st.StaffID
where (ce.StudentID == studentID) && (ce.TermID == termID) && (cl.Campus == campusID)
select new { ce, cl, t, c, st };

Generates the following LINQ-to-SQL query:

DECLARE @p0 int;
DECLARE @p1 int;
DECLARE @p2 int;
SET @p0 = 777;
SET @p1 = 778;
SET @p2 = 779;
SELECT [t0].[ClassEnrollmentID], ..., [t4].[Name]
FROM [dbo].[ei_ClassEnrollment] AS [t0]
INNER JOIN [dbo].[ei_Course] AS [t1] ON [t0].[CourseID] = [t1].[CourseID]
INNER JOIN [dbo].[ei_Class] AS [t2] ON [t0].[ClassID] = [t2].[ClassID]
INNER JOIN [dbo].[ei_Term] AS [t3] ON [t0].[TermID] = [t3].[TermID]
INNER JOIN [dbo].[ei_Staff] AS [t4] ON [t2].[Instructor] = [t4].[StaffID]
WHERE ([t0].[StudentID] = @p0) AND ([t0].[TermID] = @p1) AND ([t2].[Campus] = @p2)

I already have the SQL output working as you can see. I just need to find a way to get the IQueryable to translate into a string representing its original LINQ syntax (with an acceptable translation loss). I'm not afraid of writing it myself, but I'd like to see if anyone else has done this first.

+1  A: 

The best approach to this would be to read up on expression trees in C#. I think you may be able to use a visitor pattern over an IQueryable<T> type to recover the C# syntax. I know there are some implementations available for Expression<Func<T>>, but I can't recall ever seeing this done for a LINQ query.

UPDATE I got curious about this and started doing some research. You can access the underlying Expression Tree through the Expression property of an IQueryable<>. It looks like you would need to implement a LINQ provider that renders C# instead of SQL. This is very far from trivial. In fact I think it would be difficult to justify the amount of work that would be required unless this is an educational (non-commercial) project. But if you're undaunted, here is what looks like an excellent tutorial on LINQ providers. All the source code is available on Codeplex too.

Ryan
I'm aware of how to do it, I was wondering if anyone has tackled this before so that I wouldn't have to. I suppose it's not all that bad, though. It should be a relatively simple implementation of the expression visitor. Thanks.
James Dunne
+1  A: 

Everything IQueryable can be compiled in to an Expression object. Expressions have a Body property representing the body of the lambda expression. You may be able to, while parsing your sources, compile each expression then output the body, which should be normalized.

fatcat1111
A: 

I've done my own implementation for this since I could not find any existing work that was freely available or in source form. I put up a quick blog post about my work and included the entire C# source code for it. You can do some pretty neat stuff with it. Feel free to check it out.

http://bittwiddlers.org/?p=120

James Dunne