在ASP.NET中编写自己的提供程序类

在ASP.NET中编写自己的提供程序类,asp.net,membership-provider,dataprovider,Asp.net,Membership Provider,Dataprovider,注意:我不想编写自定义成员资格提供程序 我想编写自己的提供者类,这样我就可以在web.config中定义它,并像访问成员类一样访问它 下面是我的类的一个示例(它有许多其他静态方法): 用法:MySqlHelper.ExecuteNonQuery(“从客户中选择*) 现在,正如您所看到的,我已经硬编码了connectionstring的名称,即“MyConnString”。我计划让它充满活力 因此,我想知道是否可以将其设置为静态内置成员类,在其中可以在web.config中定义connection

注意:我不想编写自定义成员资格提供程序

我想编写自己的提供者类,这样我就可以在web.config中定义它,并像访问成员类一样访问它

下面是我的类的一个示例(它有许多其他静态方法):

用法:
MySqlHelper.ExecuteNonQuery(“从客户中选择*)

现在,正如您所看到的,我已经硬编码了connectionstring的名称,即“MyConnString”。我计划让它充满活力

因此,我想知道是否可以将其设置为静态内置成员类,在其中可以在web.config中定义connectionStringName。这样,该类就可以重复使用,而不必在web.config中将我的connectionstring命名为“MyConnString”

1:我不想在每个静态方法中都将connectionstring作为参数传递

2:我必须能够访问类似Membership.CreateUser的方法,即静态方法

我正在同时浏览网页,但任何输入/指导都会有所帮助


编辑:我已经更新了我的代码示例,以消除关于使用静态类的问题的一些混淆。下面是我发布的一篇文章来澄清这一点。很抱歉造成混淆。

这是我在一些小项目中使用的
SqlHelper
的完整代码。 但对于此类类,请小心使用
静态
。如果您将其用于Web项目,请记住,连接将在同一实例中为所有用户共享,这可能会导致严重问题

using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;

public class SqlHelper
{
    private SqlConnection connection;

    public SqlHelper()
    {
        connection = new SqlConnection();
    }

    public void OpenConnection()
    {
        // Updated code getting the ConnectionString without hard naming it.
        // Yes, if you have more than 1 you'll have problems... But, how many times it happens?

        if (WebConfigurationManager.ConnectionStrings.Length == 0)
            throw new ArgumentNullException("You need to configure the ConnectionString on your Web.config.");
        else
        {
            connection.ConnectionString = WebConfigurationManager.ConnectionStrings[0].ConnectionString;
            connection.Open();
        }
    }

    public void CloseConnection()
    {
        if (connection != null && connection.State != ConnectionState.Closed)
            connection.Close();
    }

    public DataTable ExecuteToDataTable(string sql)
    {
        DataTable data;

        SqlCommand command = null;
        SqlDataAdapter adapter = null;

        try
        {
            if (connection.State != ConnectionState.Open)
                OpenConnection();

            command = new SqlCommand(sql, connection);
            adapter = new SqlDataAdapter(command);

            retorno = new DataTable();
            adapter.Fill(data);
        }
        finally
        {
            if (command != null)
                command.Dispose();

            if (adapter != null)
                adapter.Dispose();

            CloseConnection();
        }

        return data;
    }

    public int ExecuteNonQuery(string sql)
    {
        SqlCommand command = null;

        try
        {
            if (connection.State != ConnectionState.Open)
                OpenConnection();

            command = new SqlCommand(sql, connection);
            return command.ExecuteNonQuery();
        }
        finally
        {
            if (command != null)
                command.Dispose();

            CloseConnection();
        }
    }

    public object ExecuteScalar(string sql)
    {
        SqlCommand command = null;

        try
        {
            if (connection.State != ConnectionState.Open)
                OpenConnection();

            command = new SqlCommand(sql, connection);
            return command.ExecuteScalar();
        }
        finally
        {
            if (command != null)
                command.Dispose();

            CloseConnection();
        }
    }
}
示例用法:

SqlHelper sql = new SqlHelper();
DataTable data = sql.ExecuteToDataTable("SELECT * FROM Customers");
int affected = sql.ExecuteNonQuery("INSERT Customers VALUES ('Test')");

但是如果你真的想要
static
(如果你在一个单用户环境中),只需在所有方法上设置
static

这里是我在一些小项目中使用的
SqlHelper
的完整代码。 但对于此类类,请小心使用
静态
。如果您将其用于Web项目,请记住,连接将在同一实例中为所有用户共享,这可能会导致严重问题

using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;

public class SqlHelper
{
    private SqlConnection connection;

    public SqlHelper()
    {
        connection = new SqlConnection();
    }

    public void OpenConnection()
    {
        // Updated code getting the ConnectionString without hard naming it.
        // Yes, if you have more than 1 you'll have problems... But, how many times it happens?

        if (WebConfigurationManager.ConnectionStrings.Length == 0)
            throw new ArgumentNullException("You need to configure the ConnectionString on your Web.config.");
        else
        {
            connection.ConnectionString = WebConfigurationManager.ConnectionStrings[0].ConnectionString;
            connection.Open();
        }
    }

    public void CloseConnection()
    {
        if (connection != null && connection.State != ConnectionState.Closed)
            connection.Close();
    }

    public DataTable ExecuteToDataTable(string sql)
    {
        DataTable data;

        SqlCommand command = null;
        SqlDataAdapter adapter = null;

        try
        {
            if (connection.State != ConnectionState.Open)
                OpenConnection();

            command = new SqlCommand(sql, connection);
            adapter = new SqlDataAdapter(command);

            retorno = new DataTable();
            adapter.Fill(data);
        }
        finally
        {
            if (command != null)
                command.Dispose();

            if (adapter != null)
                adapter.Dispose();

            CloseConnection();
        }

        return data;
    }

    public int ExecuteNonQuery(string sql)
    {
        SqlCommand command = null;

        try
        {
            if (connection.State != ConnectionState.Open)
                OpenConnection();

            command = new SqlCommand(sql, connection);
            return command.ExecuteNonQuery();
        }
        finally
        {
            if (command != null)
                command.Dispose();

            CloseConnection();
        }
    }

    public object ExecuteScalar(string sql)
    {
        SqlCommand command = null;

        try
        {
            if (connection.State != ConnectionState.Open)
                OpenConnection();

            command = new SqlCommand(sql, connection);
            return command.ExecuteScalar();
        }
        finally
        {
            if (command != null)
                command.Dispose();

            CloseConnection();
        }
    }
}
示例用法:

SqlHelper sql = new SqlHelper();
DataTable data = sql.ExecuteToDataTable("SELECT * FROM Customers");
int affected = sql.ExecuteNonQuery("INSERT Customers VALUES ('Test')");

但是如果你真的想要
静态的
(如果你是在一个单用户环境中),只要把
静态的
放在所有的方法上就行了。

我能想到的唯一符合你提出的条件就是使用依赖注入,一个静态构造函数,然后注入一个类似于
IConnectionStringProvider
的东西。这似乎是我能想到的最复杂的事情,所以你可能会喜欢它

编辑 在阅读您的评论之后,您似乎只希望能够引用任何连接字符串,但每个应用程序只能引用一个连接字符串。我想说的是,只需向
appSettings
添加一个名为
MySqlProviderConnection
的元素,该值是要使用的连接字符串的名称


然后在助手中,检查appsetting是否存在,获取其值,并将其传递给
ConfigurationManager.connectionString
调用。这样,您的提供者就可以使用您想要的任何连接,而无需更改任何代码。

我能想到的唯一符合您提出的条件是使用依赖项注入,一个静态构造函数,并注入类似于
IConnectionStringProvider的内容。这似乎是我能想到的最复杂的事情,所以你可能会喜欢它

编辑 在阅读您的评论之后,您似乎只希望能够引用任何连接字符串,但每个应用程序只能引用一个连接字符串。我想说的是,只需向
appSettings
添加一个名为
MySqlProviderConnection
的元素,该值是要使用的连接字符串的名称


然后在助手中,检查appsetting是否存在,获取其值,并将其传递给
ConfigurationManager.connectionString
调用。这样,您的提供商就可以使用您想要的任何连接,而无需更改任何代码。

我通常不建议跨多个请求共享一个SqlConnection实例。即使启用,也可能会遇到性能问题。我认为,当您的连接接收到非读取命令时,连接缓冲区将暂停所有当前读取,直到写入完成。你唯一真正节省的是建立连接所需的时间

SqlConnections非常有用,因此您可以配置提供程序,使其具有可用于请求客户端的最小/最大实例数。请记住,这也是由您连接到的任何数据库控制的;假设您正在连接到SQL Server实例,SQL Server有其自己的“允许的最大连接数”设置

我建议让您的公共成员接受命令字符串或命令参数,而不是让客户端决定何时打开/关闭共享SqlConnection实例。然后,与示例所建议的类似,从池中打开连接并执行命令

public IEnumerable<SqlResults> ExecuteStoredProcedure(string procedure, params SqlParameter[] parameters) {
    using(SqlConnection connection = new SqlConnection(MyConnectionStringProperty)) {
        try {
            connection.Open();

            using(SqlCommand command = new SqlCommand(procedure, connection)) {
                command.CommandType = CommandType.StoredProcedure;

                if(parameters != null) {
                    command.Parameters.AddRange(parameters);
                }

                // yield return to handle whatever results from proc execution
                // can also consider expanding to support reader.NextResult()
                using(SqlDataReader reader = command.ExecuteReader()) {
                    yield return new SqlResults {
                        Reader = reader;
                    };
                }
            }
        }
        finally {
            if(connection.State != ConnectionState.Closed) {
                connection.Close();
            }
        }
    }
}
在处理结果时不关闭连接。如果您在示例中注意到,我们为
SqlClient
对象使用了
using
语句。这种方法允许结果集处理与
MySqlHelper
分离,因为提供者类将处理可能重复的SQL提供代码,将结果处理委托给调用者,然后继续执行它必须执行的操作(即关闭连接)

至于IoC/DI,我个人使用。可以将依赖项对象作为属性或构造参数注入。将控制反转容器注册为依赖项资源管理器将允许您(除其他外)在请求资源类型时返回相同的对象。基本上,对于每个需要使用
MySqlHelper
的调用方类,当调用方类被实例化或调用方类引用其公共
MySqlHelper
属性时,可以插入相同的实例。一、 就个人而言,尽可能地选择构造函数注入。另外,当我说注入时,我的意思是你不必担心设置