首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用时,是否可以在DbContext核心中使用切分信息注入ASP.NET?

在使用时,是否可以在DbContext核心中使用切分信息注入ASP.NET?
EN

Stack Overflow用户
提问于 2021-01-15 10:23:59
回答 1查看 269关注 0票数 2

我想使用Azure SQL Elastic Database Client库来管理我的ASP.NET核心应用程序中的Server分片。

DbContext目前被注入到我的服务中。

据我所知,我需要向我的DbContext类添加一个构造函数,该构造函数接受依赖于数据的路由所需的参数(即切分映射和切分键)。

如何在注入上下文时设置这些值?

EN

回答 1

Stack Overflow用户

发布于 2022-08-09 12:56:24

是的,使用截取器的EF Core是可能的,并且工作得很好:

https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/interceptors

代码语言:javascript
复制
using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;

namespace <blah>;

public class RowLevelSecuritySqlInterceptor : DbCommandInterceptor, IRowLevelSecuritySqlInterceptor
{
    public Guid? TenantId { get; set; }

    public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
    {
        SetSessionContext(command);

        return base.ReaderExecuting(command, eventData, result);
    }

    public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result,
        CancellationToken cancellationToken = new ())
    {
        SetSessionContext(command);

        return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
    }

    public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)
    {
        SetSessionContext(command);

        return base.NonQueryExecuting(command, eventData, result);
    }

    public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = new ())
    {
        SetSessionContext(command);

        return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);
    }

    public override InterceptionResult<object> ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<object> result)
    {
        SetSessionContext(command);

        return base.ScalarExecuting(command, eventData, result);
    }
    public override ValueTask<InterceptionResult<object>> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<object> result,
        CancellationToken cancellationToken = new ())
    {
        SetSessionContext(command);

        return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);
    }

    private void SetSessionContext(IDbCommand command)
    {
        var tenantId = TenantId is null ? "null" : $"'{TenantId.Value}'";
        command.CommandText = $"EXEC sp_set_session_context @key=N'TenantId', @value={tenantId};" + command.CommandText;
    }
}

可以为DI创建一个接口:

代码语言:javascript
复制
using Microsoft.EntityFrameworkCore.Diagnostics;

namespace <blah>;

public interface IRowLevelSecuritySqlInterceptor : IDbCommandInterceptor
{
    Guid? TenantId { get; set; }
}

并将其注入DI容器:

代码语言:javascript
复制
services.TryAddTransient<IRowLevelSecuritySqlInterceptor, RowLevelSecuritySqlInterceptor>();

您的DbContext可能看起来类似于:

代码语言:javascript
复制
public partial class MyDbContext
{
    private readonly IRowLevelSecuritySqlInterceptor _rowLevelSecuritySqlInterceptor;
    ...

    public AccountServiceDbContext(
        ...,
        IRowLevelSecuritySqlInterceptor rowLevelSecuritySqlInterceptor) : base(options)
    {
        ...,
        _rowLevelSecuritySqlInterceptor = rowLevelSecuritySqlInterceptor;
    }

    ...

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(...)
            .AddInterceptors(_rowLevelSecuritySqlInterceptor, ... and other interceptors);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65734340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档