如何使用Entity Framework实现读/写分离

时间:2016-03-03 13:30:13

标签: c# sql-server entity-framework replication

我使用'主/从复制'进行数据库设置。我有一个主人和(至少)一个奴隶,可能是ℕ奴隶。为简单起见,我将讨论一个主设备,一个从设备,因为确定使用哪个从设备包括一些与手头实际问题无关的业务逻辑。

这是设置的示意图(带有ℕ奴隶):

Overview

在应用程序中(当前使用Dapper)我有以下简化的代码:

abstract class BaseRepo
{
    private readonly string _readconn;
    private readonly string _writeconn;

    public BaseRepo(string readConnection, string writeConnection)
    {
        _readconn = readConnection;     //Actually IEnumerable<string> for ℕ slaves
        _writeconn = writeConnection;
    }

    private SqlConnection GetOpenConnection(string cnstring)
    {
        var c = new SqlConnection(cnstring);
        c.Open();
        return c;
    }

    public SqlConnection GetOpenReadConnection()
    {
        return this.GetOpenConnection(_readconn);
        // Actually we use some business-logic to determine *which* of the slaves to use
    }

    public SqlConnection GetOpenWriteConnection()
    {
        return this.GetOpenConnection(_writeconn);
    }
}

class CustomerRepo : BaseRepo
{
    // ...ctor left out for brevity...

    // "Read" functions use the "read" connection
    public IEnumerable<Customer> ListCustomers()
    {
        using (var c = this.GetOpenReadConnection())
        {
            return c.Query<Customer>("select * from customers order by name");
        }
    }

    // "Write" functions use the "write" connection
    public void UpdateCustomer(Customer cust)
    {
        using (var c = this.GetOpenWriteConnection())
        {
            c.Execute("update customers set name = @name where id = @id", cust);
        }
    }
}

我的问题是;假设我想使用Entity Framework(“代码优先”,应该是相关的)而不是Dapper;我怎样才能最好地实现相同的概念;对“主”数据库执行插入/更新/删除,并对从属(或任何从属)执行选择。 EF是否支持这种情况?我需要做些什么来完成这项工作?

其他信息:我已经在SQL Server级别使用“只读”和“只写”用户作为“最后一道防线”,以防止DAL中出现任何错误。我正在寻找的是一种限制我的DAL的方法,以避免由于“不允许”操作而必须捕获SQL Server异常,并且在找到所需操作之前必须首先转到(不正确的)SQL服务器不允许。我可以使用与现在相同的方法;在方法本身中实例化/使用正确的DbContext(上例中的listcustomers / updatecustomer)。我明白了。但这意味着我必须为每个“实体”上的每个“CRUD”动作创建一个“包装”功能,这就是为什么我从一开始就从短小精悍到EF的原因;只需公开一个DBSet并让EF处理转换/ SQL查询等等,现在,希望还能找出每个动作使用哪个连接字符串。

1 个答案:

答案 0 :(得分:4)

正如其他人所建议的那样,默认情况下创建一个读/写上下文,然后创建一个继承它的只读。 另外一定要在部分类中实现一个接受另一个配置的构造函数,如果你愿意的话。

public partial class CustomerEntities : DbContext
{
    protected CustomerEntities(string nameOrConnectionString):base(nameOrConnectionString)
    {         
    }
}

public class ReadonlyCustomerEntities : CustomerEntities
{
    public ReadonlyCustomerEntities ()
        : base("name=ReadonlyCustomerEntities")
    {          
    }

    public override int SaveChanges()
    {
        // Throw if they try to call this
        throw new InvalidOperationException("This context is read-only.");
    }
}