简体   繁体   English

如何将Lambda表达式转换为Sql?

[英]How to Convert Lambda Expression To Sql?

I am developing a small framework to access the database. 我正在开发一个小框架来访问数据库。 I want to add a feature that makes a query using a lambda expression. 我想添加一个使用lambda表达式进行查询的功能。 How do I do this? 我该怎么做呢?

public class TestModel
{
    public int Id {get;set;}
    public string Name {get;set;}
}

public class Repository<T>
{
    // do something.
}

For example: 例如:

var repo = new Repository<TestModel>();

var query = repo.AsQueryable().Where(x => x.Name == "test"); 
// This query must be like this:
// SELECT * FROM testmodel WHERE name = 'test'

var list = query.ToDataSet();
// When I call ToDataSet(), it will get the dataset after running the made query.

Go on and create a LINQ Provider (I am sure you don't want to do this, anyway). 继续创建一个LINQ Provider (我相信你不想这样做)。

It's a lot of work, so maybe you just want to use NHibernate or Entity Framework or something like that. 这是很多工作,所以也许你只想使用NHibernateEntity Framework或类似的东西。

If your queries are rather simple, maybe you don't need a full blown LINQ Provider. 如果您的查询相当简单,也许您不需要一个完整的LINQ提供程序。 Have a look at Expression Trees (which are used by LINQ Providers). 看看Expression Trees (LINQ Providers使用)。

You can hack something like this: 你可以破解这样的东西:

public static class QueryExtensions
{
    public static IEnumerable<TSource> Where<TSource>(this Repo<TSource> source, Expression<Func<TSource, bool>> predicate)
    {
        // hacks all the way
        dynamic operation = predicate.Body;
        dynamic left = operation.Left;
        dynamic right = operation.Right;

        var ops = new Dictionary<ExpressionType, String>();
        ops.Add(ExpressionType.Equal, "=");
        ops.Add(ExpressionType.GreaterThan, ">");
        // add all required operations here            

        // Instead of SELECT *, select all required fields, since you know the type
        var q = String.Format("SELECT * FROM {0} WHERE {1} {2} {3}", typeof(TSource), left.Member.Name, ops[operation.NodeType], right.Value);
        return source.RunQuery(q);
    }
}
public class Repo<T>
{
    internal IEnumerable<T> RunQuery(string query)
    {
        return new List<T>(); // run query here...
    }
}
public class TestModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var repo = new Repo<TestModel>();
        var result = repo.Where(e => e.Name == "test");
        var result2 = repo.Where(e => e.Id > 200);
    }
}

Please, don't use this as it is. 请不要使用它。 This is just a quick and dirty example how expression trees can be analyzed to create SQL statements. 这只是一个快速而肮脏的例子,可以分析表达式树来创建SQL语句。

Why not just use Linq2Sql, NHibernate or EntityFramework... 为什么不使用Linq2Sql,NHibernate或EntityFramework ...

if you want to do things like 如果你想做的事情

db.Employee
.Where(e => e.Title == "Spectre")
.Set(e => e.Title, "Commander")
.Update();

or 要么

db
.Into(db.Employee)
    .Value(e => e.FirstName, "John")
    .Value(e => e.LastName,  "Shepard")
    .Value(e => e.Title,     "Spectre")
    .Value(e => e.HireDate,  () => Sql.CurrentTimestamp)
.Insert();

or 要么

db.Employee
.Where(e => e.Title == "Spectre")
.Delete();

Then check out this, BLToolkit 然后看看这个, BLToolkit

You might want to look at http://iqtoolkit.codeplex.com/ Which is very complex and i dont recommend you to build something from scratch. 你可能想看看http://iqtoolkit.codeplex.com/这是非常复杂的,我不建议你从头开始构建一些东西。

I just wrote something close to dkons's answer I will add it anyway. 我只是写了一些接近dkons的答案我还是会添加它。 Just using fluent interface nothing more. 只是使用流畅的界面而已。

public class Query<T> where T : class
{
    private Dictionary<string, string> _dictionary;

    public Query()
    {
        _dictionary = new Dictionary<string, string>();
    } 

    public Query<T> Eq(Expression<Func<T, string>> property)
    {
        AddOperator("Eq", property.Name);
        return this;
    }

    public Query<T> StartsWith(Expression<Func<T, string>> property)
    {
        AddOperator("Sw", property.Name);
        return this;
    }

    public Query<T> Like(Expression<Func<T, string>> property)
    {
        AddOperator("Like", property.Name);
        return this;
    }

    private void AddOperator(string opName, string prop)
    {
        _dictionary.Add(opName,prop);
    }

    public void Run(T t )
    {
        //Extract props of T by reflection and Build query   
    }
}

Lets say you have a model like 让我们说你有一个类似的模型

class Model
    {
        public string Surname{ get; set; }
        public string Name{ get; set; }
    }

You can use this as : 您可以将其用作:

static void Main(string[] args)
        {

            Model m = new Model() {Name = "n", Surname = "s"};
            var q = new Query<Model>();
            q.Eq(x => x.Name).Like(x=>x.Surname).Run(m);


        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM