.net 如何使实体框架数据上下文为只读

.net 如何使实体框架数据上下文为只读,.net,entity-framework,entity-framework-4,datacontext,readonly,.net,Entity Framework,Entity Framework 4,Datacontext,Readonly,我需要向第三方插件公开实体框架数据上下文。其目的是允许这些插件仅获取数据,而不允许它们发出插入、更新或删除或任何其他数据库修改命令。因此,如何使数据上下文或实体成为只读。除了与只读用户连接外,还可以对DbContext执行其他一些操作 public class MyReadOnlyContext : DbContext { // Use ReadOnlyConnectionString from App/Web.config public MyContext()

我需要向第三方插件公开实体框架数据上下文。其目的是允许这些插件仅获取数据,而不允许它们发出插入、更新或删除或任何其他数据库修改命令。因此,如何使数据上下文或实体成为只读。

除了与只读用户连接外,还可以对DbContext执行其他一些操作

public class MyReadOnlyContext : DbContext
{
    // Use ReadOnlyConnectionString from App/Web.config
    public MyContext()
        : base("Name=ReadOnlyConnectionString")
    {
    }

    // Don't expose Add(), Remove(), etc.
    public DbQuery<Customer> Customers
    {
        get
        {
            // Don't track changes to query results
            return Set<Customer>().AsNoTracking();
        }
    }

    public override int SaveChanges()
    {
        // Throw if they try to call this
        throw new InvalidOperationException("This context is read-only.");
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Need this since there is no DbSet<Customer> property
        modelBuilder.Entity<Customer>();
    }
}
公共类MyReadOnlyContext:DbContext { //使用App/Web.config中的ReadOnlyConnectionString 公共MyContext() :base(“Name=ReadOnlyConnectionString”) { } //不要公开Add()、Remove()等。 公共数据库查询客户 { 得到 { //不跟踪对查询结果的更改 返回集().AsNoTracking(); } } 公共覆盖int SaveChanges() { //如果他们想叫这个,就扔吧 抛出新的InvalidOperationException(“此上下文为只读”); } 模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder) { //因为没有DbSet属性,所以需要这个 modelBuilder.Entity(); } }
与公认的答案相反,我认为最好是这样。这样就不需要保留SaveChanges等方法来抛出异常。而且,为什么你首先需要有这样的方法?您应该设计一个类,使其使用者在查看其方法列表时不会被愚弄。公共接口应该与类的实际意图和目标保持一致,而在可接受的答案中,SaveChanges并不意味着上下文是只读的

在需要只读上下文的地方,例如在模式的读取端,我使用以下实现。它除了向消费者提供查询功能外,不提供任何其他功能

public class ReadOnlyDataContext
{
    private readonly DbContext _dbContext;

    public ReadOnlyDataContext(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IQueryable<TEntity> Set<TEntity>() where TEntity : class
    {
        return _dbContext.Set<TEntity>().AsNoTracking();
    }
}
公共类ReadOnlyDataContext
{
私有只读dbcontextu DbContext;
公共ReadOnlyDataContext(DbContext DbContext)
{
_dbContext=dbContext;
}
public IQueryable Set(),其中tenty:class
{
返回_dbContext.Set().AsNoTracking();
}
}
通过使用ReadOnlyDataContext,您只能访问DbContext的查询功能。假设您有一个名为Order的实体,那么您将以如下方式使用ReadOnlyDataContext实例

readOnlyDataContext.Set<Order>().Where(q=> q.Status==OrderStatus.Delivered).ToArray();
readOnlyDataContext.Set().Where(q=>q.Status==OrderStatus.Delivered.ToArray();
如果您想手动选择(并限制)通过此新上下文公开哪些实体,则可以使用另一个选项。您可以删除上面基于泛型的方法(包含tenty的完整块),并使用类似于下面的方法

    public IQueryable<MyFirstThing> MyFirstHandPickThings => this.dbContext.Set<MyFirstThing>().AsNoTracking();

    public IQueryable<MySecondThing> MySecondHandPickThings => this.dbContext.Set<MySecondThing>().AsNoTracking();
public IQueryable MyFirstHandPickThings=>this.dbContext.Set().AsNoTracking();
public IQueryable MySecondHandPickThings=>this.dbContext.Set().AsNoTracking();

为他们提供一个没有数据库写入权限的用户的上下文。谢谢。我正在使用SQLite数据库。刚发现它可以通过连接字符串选项以只读模式打开。不要给他们一个
DbContext
,给他们一个
IQueryable
或几个。很明显你是一个“内鬼”:-这比“只读”连接有趣得多注意使用
AsNoTracking()
将无法使用延迟加载。不要忘了重写
公共重写任务savechangesync()
。不要依赖于此,因为
(上下文作为IObjectContextAdapter)。ObjectContext.SaveChanges()
仍然可以工作。最好的选择是使用
DbContext(字符串名称或连接字符串)contstructor,带有用于数据库创建的读/写连接字符串和之后的只读连接字符串。@EntityFrameworkCore中的bricelam应该是
public IQueryable Customers=>Set().AsNoTracking()
此方法是否允许使用db_datareader only sql登录?如果使用标准DBContext EF,即使我的查询代码不包含任何SaveChanges(),创建表的权限也会被拒绝。如果让它继承自
IDisposable
,而不是使用Set,我建议使用查询
publicIQueryable Get(),其中tenty:class{return}dbContext.Query().AsNoTracking();}
@hkarask-我不确定我会这么做。由于此调用未创建DbContext,因此不应处置它。这可能会导致以后很难找到一些bug。@AllanNielsen查询被标记为已弃用。根据它的设置,应该使用。