我正在构建一个带有代码优先数据库的ASP.NET MVC3网站,并提出以下问题:
是否可以使用附加参数集创建MyDbContext类的实例,该参数集将用于过滤对mydbcontext的调用结果。
我想用它来将结果集限制为在我的asp.net mvc网站上登录的当前用户。
任何指示都会很棒!
答案 0 :(得分:1)
我不明白为什么这应该是一个问题。这样的事情应该有效:
public class Northwind : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
public class FilteredNorthwind : Northwind
{
public IQueryable<Products> GetFilteredProducts(string userRole)
{
return Products.Where(product => product.UserRole == userRole);
}
}
<强>更新强>
为了使您的MyDbContext
无法被滥用,您可以将所有数据库代码和模型放入单独的项目/程序集中。然后将DbContext
设为internal
课程(而不是public
),然后创建一个包裹public
和FilteredDbContext
的{{1}}课程(MyDbContext
)公开允许您只获取允许查看的数据的方法。然后在主程序集(您的Web项目)中,您将只能使用FilteredDbContext
。
所以,例如:
internal class Northwind : DbContext // note: internal class
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
public class FilteredNorthwind // note: does not inherit from `Northwind`
{
private readonly _dbContext = new Northwind();
public IQueryable<Products> GetProducts(string userRole)
{
return _dbContext.Products.Where(product => product.UserRole == userRole);
}
}
如果Northwind
和FilteredNorthwind
与您的网络应用程序位于不同的程序集中,则只能从您的网络应用程序中实例化FilteredNorthwind
。
更新2
如果您使用ViewModel,那么您的网络应用程序无法返回到某个类别的所有产品列表,因为您只提取了所需的属性(并且只提取了允许用户查看的属性)。 / p>
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
public IEnumerable<Products> GetProducts(string userRole)
{
return _dbContext.Products
.Where(product => product.UserRole == userRole)
.Select(product => new ProductViewModel
{
Id = product.Id,
Name = product.Name,
Price = product.Price
};
}
答案 1 :(得分:0)
您可以在上面创建一个图层并隐藏生成的图层并创建一个您自己的DbContext,它源自生成的MyDbContext。只是一个疯狂的猜测,但它似乎合乎逻辑,所以你可以实现自己的参数集,仍然使用生成的参数集。
答案 2 :(得分:0)
我会这样做:
public interface IUserContext {
string User { get; set; }
}
public class Database : DbContext {
public IDbSet<Product> Products { get; set; }
}
public class AuthorizedDatabase {
private readonly Database _database;
private readonly IUserContext _userContext;
public AuthorizedDatabase(Database database, IUserContext userContext) {
_database = database;
_userContext = userContext;
}
private bool Authorize<TEntity>(TEntity entity) {
// Some code here to look at the entity and the _userContext and decide if it should be accessible.
}
public IQueryable<Product> Products {
get {
return _database.Products.Where(Authorize);
}
}
}
这将允许我干净地抽象出授权周围的实际逻辑(并且您的IUserContext接口可以根据您的确切需求进行简单或复杂的处理。)
要确保用户无法使用导航属性(例如,Product.Category.Products)绕过此保护,您可能需要关闭延迟加载并显式加载所需的相关实体。
从ADO.NET团队博客中查看此帖子的想法:loading related entities