如何为与数据库连接的类提供连接字符串?

时间:2012-12-28 20:09:22

标签: c# events connection connection-string

我在C#中尝试数据访问。我正在编写一个具有Save(object o)方法的类,它将遍历每个对象的属性,并使用属性将它们与数据库匹配。

我的问题是我的类需要获取连接字符串,但我希望用户提供它。我基本上不希望它仅限于配置文件。这就是我到目前为止所想到的:

  • 在每个连接之前触发一个事件,用户通过自定义EventArgs类提供字符串(类似于如何通过{{{{}}}将自己的对象实例提供给ASP.NET ObjectDataSource 1}} event)
  • 我的数据访问类中的属性
  • 两者的组合,如果事件没有订阅者,则会使用属性的值

我只是想知道其他可能性是什么以及这种情况下最好的策略是什么?

2 个答案:

答案 0 :(得分:2)

事件不会很自然,因为如果不存在单个订户,您的代码就会中断。事件适用于用户数量与提升事件的课程无关的用例。

使用属性或接口(如IConnectionProvider)注入连接字符串。界面版本非常适合与DI容器一起使用。

答案 1 :(得分:1)

半同意usr,无论你走哪条路,你都会想要创建一个IConnectionProvider。

但是,我认为这取决于您希望允许开发人员使用您的课程的灵活性。

您是否会强制您的类的每个实例具有保持不变的全局连接并用于需要访问数据库的所有方法调用?如果是这样,那么你的类需要在其构造函数中使用IConnectionProvider。

您是否要提醒开发人员并让他们在班级状态发生变化时灵活地更改连接?如果是这样,那么提供一个事件可能是个不错的选择。

您的类是静态的,还是要强制开发人员使用方法调用提供不同的连接?然后,每个方法都应该采用IConnectionProvider。

您需要决定您希望在课堂上允许的灵活性,并根据该选择做出选择。

如果您想要允许极大的灵活性和自定义,您可能需要查看lambda表达式。使用它们,您可以允许开发人员提供您将在代码中的某个位置调用的方法。使用lambda表达式,我能够通过编写通用数据库方法来整合代码,其中调用者只需提供代码来读取我为其设置的IDataReader并处理捕获任何异常以及关闭和处理所需的任何数据库对象。

编辑:以下是我合并连接代码的示例。

    public static T ExecuteReader<T>(IDbConnection connection, string commandText, Func<IDataReader, T> readData) where T : class
    {
        IDbCommand command = connection.CreateCommand();
        command.CommandText = commandText;

        try
        {
            connection.Open();
            IDataReader reader = command.ExecuteReader();
            T returnValue = readData(reader); //Call the code provided by the caller and get the return object.

            reader.Close();
            reader.Dispose();

            return returnValue; //Return their return object.
        }
        finally
        {
            if (command != null)
            {
                command.Dispose();
            }
            if (connection != null)
            {
                try
                {
                    if (connection.State != ConnectionState.Closed)
                    {
                        connection.Close();
                    }
                }
                finally
                {
                    connection.Dispose();
                }
            }
        }
    }

示例用法:

MyDataList.AddRange(
    Database.ExecuteReader<List<MyDataModel>>( //Tell ExecuteReader what type of object to return
    connection, //Pass in the connection
    commandString, //Pass in the command
    delegate(IDataReader reader) //This code is called from inside the ExecuteReader method.
    {
        List<MyDataModel> List = new List<MyDataModel>();
        while (reader.Read())
        {
            //Read each record, transform it into MyDataModel, then add it to the List.
        }
        return List;
    }
}));

创建了通用的ExecuteReader方法,因为用于创建命令,打开连接和处理所有命令的代码保持不变并为每个对象进行复制。这可以防止不必要的代码复制。唯一真正改变的是如何将对象从IDataReader转换为类,以便ExecuteReader方法的调用者能够提供将执行特定转换的代码。

这可能不适合你,因为你正在以1:1的方式映射对象并提供一种自动转换它们的方法,但就我而言,我无法依赖它。