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());