配置实体框架以调用SQL Server表功能,而不是特定实体上的表



i有一个实体表(例如,文档(,每个文档可能都与其连接了一个不同的实体(例如,可以说(。许可有文档表的外键。

示例:

架构

Document -> Id | Data
Permission -> Id | EntityId | PermissionData

内容

Document -> 1 | "This is my first doc"
Permission -> 12 | 1 | "This is doc 1's permission set"

如果Permission是一张表,我不会有任何问题 - 我只需在查询中使用Include方法并接收连接的权限:

ctx.Include(d => d.Permission)...

但是,Permission实际上是一个复杂的方案,它包含多个表,并使用SQL Server表值函数进行计算。

我试图像每个常规表实体一样创建一个Permission实体,并且只需配置实体框架即可执行数据库函数调用,而不是表加入。

如果权限是一张表,我会将其包含在我的查询中,我希望SQL执行看起来像这样:

select * 
from document d 
join permission p on d.Id = p.EntityId

我想实现这样的目标:

select * 
from document d 
join fn_getPermissions(p1,p2,p3...) p on d.Id = p.EntityId

让我们假设params p1 ... pn是硬编码的,但是我需要在c#end而不是在sql server上默认它们。

我看到了配置实体使用实体框架存储过程的选项,但是我没有看到任何可以使用存储过程进行查询的地方,而是用于插入,删除等。

我知道如何调用DBFunctions(使用Conventions( - 我不是在寻找明确的函数调用。我想将许可实体视为表实体,主要是因为我在实体框架上使用了odata,而我不想仅仅为这种情况创建特定方法。

有什么方法可以完成这种行为?我正在使用EF 6.x(不是核心(。

取决于您的comlex表结构,这可能会起作用。您基本上可以从SQL构建一个实体,但是为此,您应该在DB中有一个表格中的表格,即一个具有所需数据的表(您可以使用其他表来解释它,但是您想要的数据是假设仅在许可表中(。比您可以使用STH:

   this.Context.Permissions
.FromSql(@"select permName, permDesc from document d join fn_getPermissions(@p1,@p2,@p3...) p on d.Id = @entityId"
, new SqlParameter("p1", val)
, new SqlParameter("p2", val)
, new SqlParameter("p3", val)
, new SqlParameter("entityId", val))
.Select(c => new { c.permName, c.permDesc });

如您所见,您可以选择一个动态对象,或者如果要使用类型,则可以施放它,但是您应该浏览上下文的一个表格,在这种情况下,在这种情况下,"权限"。

我用解决方法解决了这个临时性。

我不会接受我的答案,因为我不相信这是最好的做法,也许其他人会提出更好的解决方案。此解决方法对我有用,因为我只想读取权限。如果您选择实现此解决方案,请小心并检查其生成的SQL查询以确保它适合您。

因此,为了实现我所需的目标,我将实体映射到虚拟表。

modelBuilder.Entity<Permission>().ToTable("Dummy_Permission_Table");

然后,我创建了一个自定义IDbCommandInterceptor并覆盖了ReaderExecuting方法,因为它是我唯一相关的方法。

public class PermissionDbCommandInterceptor : IDbCommandInterceptor
{
    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }
    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }
    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
       // get the params and create the function call
       command.CommandText = command.CommandText.Replace("[Dummy_Permission_Table]","fn_getPermissions(p1,p2,p3..)");
    }
    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
}

最后,我已经注册了拦截器:

DbInterception.Add(new PermissionDbCommandInterceptor());

最新更新