c# - 通过单一方法但使用多个查询的数据库连接

标签 c# database visual-studio

您好,出于我自己的好奇心,我问一个简单的问题。我试图不重复我的代码。我仍在学习如何正确使用参数和参数,所以我想它将通过这条路线,这是我的代码。

public void MultiChoiceLight()
    {
        lCon = new SQLiteConnection(@"Data Source=knowledge.db;Version=3");
        lCon.Open();
        string query1 = $"UPDATE testOrder SET question='{QuestionsFromDb.question}', choice1='{QuestionsFromDb.choice1}" +
            $"', choice2='{QuestionsFromDb.choice2}', choice3='{QuestionsFromDb.choice3}', choice4='{QuestionsFromDb.choice4}' " +
            $"WHERE qid={QuestionsFromDb.b}";
        lCmd = new SQLiteCommand(query1, lCon);
        lCmd.ExecuteNonQuery();
        lDr = lCmd.ExecuteReader();
        lCon.Close();
    }

public void MultiChoiceButtonNext()
    {
        lCon = new SQLiteConnection(@"Data Source=knowledge.db;Version=3");
        lCon.Open();
        string query = $"SELECT * FROM testOrder WHERE qid={qid}";
        lCmd = new SQLiteCommand(query, lCon);
        lCmd.ExecuteNonQuery();
        lDr = lCmd.ExecuteReader();
    }

好吧,我想弄清楚的是,每个方法中的代码行仅使用一次,然后输入查询,这样我就可以通过方法尽可能多次地执行此操作。我有很多这样的方法,并且真的很想缩短我的代码。在你说之前,我知道 lambda 表达式和实体,但我没有在我尝试制作的应用程序中使用它。如果我可以将查询保存到类文件中,然后从那里调用它们以使我的代码看起来整洁,那就太好了。谢谢阅读。

最佳答案

您可以将 SQL 连接包装在某种帮助程序类中,无论您需要什么地方:

// TODO: Parametrized queries?
public class SQLConnectionHelper
{
    private readonly string _connectionString;

    // TODO: Parameterless constructor which gets connection string from config?

    public SQLConnectionHelper(string connectionString)
    {
        _connectionString = connectionString;
    }

    private TResult WithConnection<T>(Func<SQLiteConnection, TResult> func)
    {
        // TODO: try-catch-rethrow-finally here

        using (var connection = new SQLiteConnection(_connectionString))
        {
            _sqliteConnection.Open();

            var result = func(_sqliteConnection);

            _sqliteConnection.Close();

            return result;
        }
    }

    public void ConnectExecuteReader(string query, Action<SQLiteDataReader> action)
    {
        WithConnection(conn => {
            var reader = new SQLiteCommand(query, conn).ExecuteReader();
            action(reader);
        });
    }

    public int ConnectExecuteNonQuery(string query)
    {
        return WithConnection(conn => {
            return new SQLiteCommand(query, conn).ExecuteNonQuery();
        });
    }
}

用法:

public class YourClass
{
    private readonly SQLConnectionHelper _sql = new SQLConnectionHelper(@"Data Source=knowledge.db;Version=3");

    public void MultiChoiceLight()
    {
        string query1 = $"UPDATE testOrder SET question='{QuestionsFromDb.question}', choice1='{QuestionsFromDb.choice1}" +
        $"', choice2='{QuestionsFromDb.choice2}', choice3='{QuestionsFromDb.choice3}', choice4='{QuestionsFromDb.choice4}' " +
        $"WHERE qid={QuestionsFromDb.b}";

        int result = _sql.ConnectExecuteNonQuery(query1);
    }

    public void MultiChoiceButtonNext()
    {
        _sql.ConnectExecuteReader($"SELECT * FROM testOrder WHERE qid={qid}", r => {
            // process your reader here, outside of this lambda connection will be closed
        });
    }
}

好处:

  1. SQL连接类型被封装在SQLConnectionHelper中并且可以被替换,客户端几乎是从特定类型的SQL连接中抽象出来的(除了SQLiteReader,可以重写);
  2. 封装了SQL连接配置(连接字符串);
  3. 封装了 SQL 连接错误处理,您可以抛出一些特定的 CustomSQLException 并且只需在一处定义它;
  4. 封装了SQL连接的打开/关闭。例如,您可以拥有一个连接,而不是每次调用都连接,并且只需在一处进行更改;
  5. 许多其他 OOP 对于维护和 future 可扩展性的好处;
  6. SQLConnectionHelper 可以实现IDisposable 并清理连接资源。

这个解决方案可能看起来有点太“函数式”,因为使用高阶函数,您可以以更 OOP 的方式重写它,它只是为了给出想法,而不是实现。

关于c# - 通过单一方法但使用多个查询的数据库连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43624719/

相关文章:

c# - 将 C# 日期时间转换为 0000-00-00 00 :00:00 to MySQL

database - 为 Couch Base Server 1.8 和 2.0 构建 Erlang 客户端

json - 通过Retrofit 2将数据存储到Realm中

visual-studio - Visual Studio 2017 RC 安装错误 0x80131500 无法反序列化包

javascript - 预期的标识符、字符串或数字,带 *[Symbol.iterator]

c# - Java中数组继承自什么?我可以这样做吗?

c# - 如何使用 EPPlus 一次插入一行

java - 在 MySQL 中添加 NullPointerException

asp.net 编译时错误 - 对象引用未设置到对象的实例

c# - 在 Window 上实现搜索功能的方法