Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架单元测试(或类似测试),以确保在使用DbSet时,始终调用特定的扩展方法_C#_Entity Framework_Unit Testing - Fatal编程技术网

C# 实体框架单元测试(或类似测试),以确保在使用DbSet时,始终调用特定的扩展方法

C# 实体框架单元测试(或类似测试),以确保在使用DbSet时,始终调用特定的扩展方法,c#,entity-framework,unit-testing,C#,Entity Framework,Unit Testing,我想强制执行一项要求,即无论何时与db.Users交互,都需要调用特定的扩展方法。下面是一些更具体的信息 通过实体框架与数据库交互时,我有以下查询(db是DbContext实例): 在整个应用程序中,此查询将一直变化(WHERE子句通常会不同,等等)。因此,我要求您必须始终调用fromOrganization()扩展方法,以便首先按组织过滤返回的所有数据 这是为了防止任何人看到属于不同组织的数据,但我一直在研究如何实现这一点 我是否可以编写一个单元测试来提醒开发人员使用用户DbSet时没有组织过

我想强制执行一项要求,即无论何时与db.Users交互,都需要调用特定的扩展方法。下面是一些更具体的信息

通过实体框架与数据库交互时,我有以下查询(db是DbContext实例):

在整个应用程序中,此查询将一直变化(WHERE子句通常会不同,等等)。因此,我要求您必须始终调用fromOrganization()扩展方法,以便首先按组织过滤返回的所有数据

这是为了防止任何人看到属于不同组织的数据,但我一直在研究如何实现这一点

我是否可以编写一个单元测试来提醒开发人员使用用户DbSet时没有组织过滤?如果没有,我有没有其他途径可以达到同样的保护水平

如果很重要,扩展方法本身如下所示:

public static IQueryable<User> FromOrganisation(this IQueryable<User> u, int organisationId)
{
    return u.Where(x => x.OrganisationId == organisationId);
}
来自组织的公共静态IQueryable(此IQueryable u,int-OrganizationID)
{
返回u.Where(x=>x.OrganizationID==OrganizationID);
}
我的最终解决方案

我改变了我的背景如下:

public DbSet<User> Users { get; set; }
公共数据库集用户{get;set;}
成为:

[Obsolete("MUST use service!")]
public DbSet<User> UsersUnfiltered { get; set; }


public IQueryable<User> Users(int id)
{
    #pragma warning disable 618
    return UsersUnfiltered.Where(x => x.OrganisationId == id);
    #pragma warning restore 618
}
[过时(“必须使用服务!”)]
public DbSet usersunferred{get;set;}
公共IQueryable用户(int id)
{
#pragma警告禁用618
返回UsersUnfiltered.Where(x=>x.OrganizationID==id);
#pragma警告恢复618
}
这样做的目的是鼓励您使用Users方法返回按组织筛选的用户列表。可以像往常一样对其进行进一步筛选、联接和查询等

如果需要,您还可以访问UsersUnfiltered数据库集,但如果使用它,则会生成编译器警告。您可以通过在#pragma warning disable 618指令中访问该警告来抑制该警告

有了这一点,您就有了代码来防止您在不按组织过滤的情况下使用用户数据,除非您真的打算这样做


感谢@mark_h帮助我找到了这个解决方案。

您提出的一个问题是,如果您可以强制使用它,那么即使在您从上下文进行初始查询之后,您每次想要子查询一组用户时都必须强制使用它

var allUsersOfOrganisation1 = db.Users.FromOrganisation(1)
// some code...
var someUsersOfOrganisation1 = allUsersOfOrganisation1.FromOrganisation(1).Where(...)
如果强制使用扩展方法,如何区分对包含所有用户的集合的查询和筛选的子集

您可以通过包装实体模型并仅通过强制实施唯一组织id的方法公开用户来实现您想要的结果

public class WrappedEntities
{
    private MyEntityFramework Entities = new MyEntityFramework();

    //regular public entities
    public DbSet<Organisation> Organisations { get { return Entities.Organisation; } set { Entities.Organisation = value as DbSet<Organisation>; } }

    //Special case
    public IQueryable<User> Users(int id)
    {
        return Entities.Users.Where(x => x.OrganisationId == organisationId);
    }

    //other wrapped methods...
    public int SaveChanges()
    {
        return Entities.SaveChanges();
    }
}
公共类包装属性
{
私有MyEntityFramework实体=新建MyEntityFramework();
//正规公共实体
公共DbSet组织{get{return Entities.organization;}set{Entities.organization=值为DbSet;}
//特例
公共IQueryable用户(int id)
{
返回实体.Users.Where(x=>x.OrganizationID==OrganizationID);
}
//其他包装方法。。。
公共int SaveChanges()
{
返回实体。SaveChanges();
}
}

如果你给这个类一个接口,你也可以为了单元测试的目的模拟它。

你需要公开
用户集吗?如果您仅通过
IQueryable GetOrganizationUsers(int-id)
获取用户会怎么样?这是一个非常有趣的问题。我的上下文公开了目前DbSet属性的列表。但是,我使用这些方法不仅用于查询,还用于向数据库中添加新记录,因此我认为它们必须在某个位置公开。您可以在上下文中添加
AddUser
方法。另一个选项是使用EntityFramework.DynamicFilters.com定义全局过滤器。很抱歉,我的回复太晚了-我昨天实现了这个功能,它的工作原理与它应该的完全一样。我将在我的原始问题中发布我的最终解决方案。非常感谢你的帮助。
public class WrappedEntities
{
    private MyEntityFramework Entities = new MyEntityFramework();

    //regular public entities
    public DbSet<Organisation> Organisations { get { return Entities.Organisation; } set { Entities.Organisation = value as DbSet<Organisation>; } }

    //Special case
    public IQueryable<User> Users(int id)
    {
        return Entities.Users.Where(x => x.OrganisationId == organisationId);
    }

    //other wrapped methods...
    public int SaveChanges()
    {
        return Entities.SaveChanges();
    }
}