1

只是想知道是否可以在没有 linq 或 ORM 的情况下进行延迟加载。我需要做一些不适合 ORM 的查询。我还需要在方法之间传递查询。此外,我找不到任何微型工具来实现这一点。有没有办法做到这一点?

var q = "Select Name from Test1"

现在我们必须添加一个 OR 或 AND 或 IN 或其他东西

这个查询将被传递给不同的方法进行过滤。有没有办法使用微型 ORM 或 AD Hoc SQL 查询来做到这一点?

4

6 回答 6

7

您可以直接使用数据读取器,也可以通过一个懒惰地评估它的类来完成。请参阅http://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.100).aspx

所以作为一个粗略的例子,你可能会做这样的事情

public class LazyReader {
    SqlDataReader m_reader;
    SqlCommand m_command;
    SqlConnection m_connection;
    public LazyReader(SqlConnection connection, String sql)
    {
        m_command = new SqlCommand(sql, connection);
        m_connection = connection;
    }

    public IEnumerable<Object[]> read()
    {
        using (m_connection) {
            m_connection.Open();
            m_reader = command.ExecuteReader();
            while (m_reader.HasRows)
            {
                while (m_reader.Read())
                {
                    Object[] values = new Object[m_reader.FieldCount];
                    m_reader.GetValues(values);
                    yield return values;
                }
                m_reader.NextResult();
            }
            m_reader.Close();
        }
    }
}

您可能需要对示例进行一些摆弄,但想法是使用 DataReader 并逐个读取行,并通过 IEnumerable 将结果与 yield return 一起传递,这将导致惰性求值。然后,您可以传递 IEnumerable 并随意阅读。请注意确保您阅读一致,否则 SQLConnection 将在 30 秒后终止而没有任何活动。

于 2012-07-09T11:35:24.333 回答
6

为什么不直接使用FuncorAction并让它定义您的查询,所以当您将它传递给下一个函数时,它可以在需要时执行。

它的功能就像延迟加载一样。

于 2012-05-23T01:27:12.523 回答
5

您可以使用

懒人<T>

为了这。正如 James 所建议的,它依赖于 Func,但也支持缓存和线程安全。

http://msdn.microsoft.com/en-us/magazine/ff898407.aspx

编辑:由于您现在正在寻找 ORM 的其他功能,例如过滤和排序,但是可以灵活地编写原始 sql,我建议您查看诸如 Entity Framework 或 Nhibernate 之类的 ORM 并使用它们的一些原始 sql 功能在适当的地方喜欢

session.CreateSQLQuery(sql);

ORM 还允许您在动态添加 where 过滤器时进行更强的键入以消除错误。

于 2012-07-11T08:52:21.070 回答
1

Lazy<T>门课听起来像你要找的。正如 Kaido 和 James 建议的那样,您需要定义一个执行实际加载的方法,然后将其传递给延迟加载(实际上是已初始化)对象的 ctor。

前任:

public class SomeClass
{
     Lazy<List<string>> myLazy = new Lazy<List<string>>(LoadData);
     private List<string> LoadData()
     {
        //open connection, execute your query, read/project data into a List, etc

        return new List<string> { "Hello", "My", "Name", "Is", "Earl" };
     }
}

该类的Lazy<T>行为与您可能期望的完全一样 - 它推迟了包含对象的初始化,直到通过Value属性引用它。有关详细信息,请参阅MDSN 参考

于 2012-07-12T16:02:57.750 回答
1

您可能需要在设计中考虑存储库模式。存储库决定如何向客户端类提供东西。它是如何完成的对消费者来说并不重要,它可以在需要的地方传递或注入。

还要考虑对象缓存,例如RedisMemcached。如果您需要非顺序地“延迟加载”对象,这些特别有用。可以进行复杂的 SQL 查询以仅返回主键而不是几十个大数据字段。存储查询的所有键,然后按需创建业务对象。

如果您的实现超出了您的要求,Repository 可以在不影响使用它的类的情况下轻松改进。

于 2012-07-13T02:27:16.157 回答
1

一种方法是将查询表示为某种内存中的对象,您可以进一步向其中添加表达式。例如,使用一些组成的对象层次结构:

var q = Table("Test1").Select("Name");

您可以通过添加过滤器来进一步细化:

q = q.Where("ID= 1");

但这当然意味着您正在重新发明IQueryable. 你最好只接受 LINQ 并选择一个提供程序(LINQ2SQL 或 LINQ2EF 等)。

另一种方法是保留字符串即席表示:

var q = "Select Name from Test1";

但是你如何添加过滤器?您必须解析字符串并插入 WHERE 子句。这远非微不足道。您很快就会实现一个成熟的 SQL 解析器(lex + yaccbison + flex)和一个抽象语法树,然后将其序列化为一个新的 SQL 字符串。一旦你开始考虑连接(支持起来相当简单)、子查询(讨厌)、递归表表达式(哎哟),事情就会变得越来越复杂。只需浏览这个站点,看看可以得到多么复杂的 SQL 查询,并想象为实现一个解析。

我见过的许多项目都试图将查询表示为某种中间形式,例如。一个结构(字段列表、表名、WHERE 条件列表、ORDER BY 子句列表等),然后在这些列表表示中添加新条目(在 WHERE 列表中添加新条目以添加新过滤器)。但是,回想起来,这些表示与 LINQ 提供的相比显得苍白无力。我承认,LINQ 是一个全有或全无的产品,您要么承诺要么不承诺。但试图重新发明它只会揭示问题的复杂性。今天我将从另一端解决问题:从 LINQ 开始并尽量避免它,不要让它成长为无法控制的查询生成工具的可怕怪物,其中项目的每一层都添加了一些过滤器到IQueryable然后用优化器甚至无法解开的东西轰炸服务器。

PS。为什么我写 AREL是对整个问题的好读物。

于 2012-07-24T10:07:10.727 回答