So I Just got a recommendation from Amazon for LINQ to Objects Using C# 4.0: Using and Extending LINQ to Objects and Parallel LINQ (PLINQ).
It says that the book introdu
What I've done that gets me the result is this, but I would think there is a better way.
using (SqlConnection connection = new SqlConnection(this.Connection.ConnectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(query, connection);
SqlDataReader reader = command.ExecuteReader();
reader.Cast<IDataRecord>().AsQueryable().Dump();
}
Joe's answer is cool. I have an idea how to simplify the usage. If you add this to the extension class:
public static class Extensions
{
public static IEnumerable<dynamic> ExecuteSql(this UserQuery uq, string sql)
{
var connStr="Provider=SQLOLEDB.1;"+uq.Connection.ConnectionString;
OleDbConnection connection = new OleDbConnection(connStr);
DataSet myDataSet = new DataSet();
connection.Open();
OleDbDataAdapter DBAdapter = new OleDbDataAdapter();
DBAdapter.SelectCommand = new OleDbCommand(sql, connection);
DBAdapter.Fill(myDataSet);
var result = myDataSet.Tables[0].AsDynamic();
return result;
}
}
It allows to use queries like this in LINQPad:
void Main()
{
var query1 = from cust in this.ExecuteSql("SELECT * from Customers")
where cust.ContactName.StartsWith ("C")
orderby cust.ContactName
select new { cust.CustomerID, cust.ContactName, cust.City };
query1.Dump();
}
N.B.: You need to add the following references:
System.Data.OleDb
from the System.Data
assembly to the query propertiesAdd System.Dynamic
to the query properties
uq.Connection
is only available if you have associated a database via the Connection dropdown. If you have selected "<none>"
, a compile error will occur.
Update:
I noticed that Joe has added a function ExecuteQueryDynamic
in the latest Beta v4.53.03 of LinqPad, which can be used to achieve this, for example:
void Main()
{
var q=this.ExecuteQueryDynamic("select * from Customers");
q.Dump();
}
This will return the Customers
table from the Northwind database as IEnumerable<dynamic>
, using a Linq2Sql connection.
Here's an idea: by combining LINQ with dynamic, you can query untyped datasets as though they were typed.
For instance, suppose that myDataSet is an untyped DataSet. With dynamic typing and an extension method called AsDynamic(), the following is possible:
var query = from cust in myDataSet.Tables[0].AsDynamic()
where cust.LastName.StartsWith ("A")
orderby cust.LastName, cust.FirstName
select new { cust.ID, cust.LastName, cust.FirstName, cust.BirthDate };
Here's how to define the AsDynamic extension method. Notice how it returns IEnumerable of dynamic, which makes it suitable for LINQ queries:
public static class Extensions
{
public static IEnumerable<dynamic> AsDynamic (this DataTable dt)
{
foreach (DataRow row in dt.Rows) yield return row.AsDynamic();
}
public static dynamic AsDynamic (this DataRow row)
{
return new DynamicDataRow (row);
}
class DynamicDataRow : DynamicObject
{
DataRow _row;
public DynamicDataRow (DataRow row) { _row = row; }
public override bool TryGetMember (GetMemberBinder binder, out object result)
{
result = _row[binder.Name];
return true;
}
public override bool TrySetMember (SetMemberBinder binder, object value)
{
_row[binder.Name] = value;
return true;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _row.Table.Columns.Cast<DataColumn>().Select (dc => dc.ColumnName);
}
}
}
By subclassing DynamicObject, this takes advantage of custom binding - where you take over the process of resolving member names yourself. In this case, we bind the get and set member access to retrieving or storing objects in the underlying DataRow.