Entity Framework 데이터 컨텍스트를 읽기 전용으로 만드는 방법


112

Entity Framework 데이터 컨텍스트를 타사 플러그인에 노출해야합니다. 목적은 이러한 플러그인이 데이터 만 가져 오도록 허용하고 삽입, 업데이트 또는 삭제 또는 기타 데이터베이스 수정 명령을 실행하지 못하도록하는 것입니다. 따라서 데이터 컨텍스트 또는 엔티티를 읽기 전용으로 만들려면 어떻게해야합니까?


3
데이터베이스에 대한 쓰기 권한이없는 사용자에게 컨텍스트를 제공하십시오.
vcsjones

감사. SQLite 데이터베이스를 사용하고 있습니다. 연결 문자열 옵션을 통해 읽기 전용 모드로 열 수 있다는 것을 방금 알아 냈습니다.
Harindaka

2
DbContext그들에게 하나 IQueryable또는 여러 개를 주지 마십시오 .
ta.speot.is dec.

답변:


178

읽기 전용 사용자와 연결하는 것 외에도 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>();
    }
}

1
당신이 '내부 남자'라는 것이 분명했습니다. :)-이것은 '읽기 전용'연결보다 훨씬 더 흥미 롭습니다
NSGaga- 대부분 비활성화 됨

6
를 사용 AsNoTracking()하면 지연로드를 사용할 수 없습니다.
Tom Pažourek

@ TomPažourek 그게 사실인지 모르겠습니다 ... EF는 여전히 지연 로딩 프록시를 생성한다고 생각하지만 신원 확인이 약간 이상해질 수 있습니다.
bricelam

3
재정의 public override Task<int> SaveChangesAsync()하는 것도 잊지 마십시오 .
Pete

7
(context as IObjectContextAdapter).ObjectContext.SaveChanges()여전히 작동 하므로 이것에 의존하지 마십시오 . 최선의 선택은 DbContext(string nameOrConnectionString);데이터베이스 생성에 대한 읽기 / 쓰기 연결 문자열과 나중에 읽기 전용 연결 문자열과 함께 생성자 를 사용하는 것입니다.
Jürgen Steinblock

33

받아 들여지는 대답과 달리 상속 보다 구성을 선호하는 것이 더 낫다고 생각합니다 . 그러면 예외를 발생시키기 위해 SaveChanges와 같은 메서드를 유지할 필요가 없습니다. 더군다나 애초에 그러한 방법이 필요한 이유는 무엇입니까? 소비자가 메서드 목록을 볼 때 속지 않는 방식으로 클래스를 디자인해야합니다. 공용 인터페이스는 클래스의 실제 의도 및 목표와 일치해야하며 허용 된 답변에서 SaveChanges가 있다고해서 Context가 읽기 전용임을 의미하지는 않습니다.

CQRS 패턴 의 읽기 쪽과 같이 읽기 전용 컨텍스트가 필요한 곳에서는 다음 구현을 사용합니다. 소비자에게 쿼리 기능 외에는 아무것도 제공하지 않습니다.

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를 사용하면 DbContext의 쿼리 기능에만 액세스 할 수 있습니다. Order라는 엔티티가 있다고 가정하면 다음과 같은 방식으로 ReadOnlyDataContext 인스턴스를 사용합니다.

readOnlyDataContext.Set<Order>().Where(q=> q.Status==OrderStatus.Delivered).ToArray();

이 방법을 사용하면 db_datareader 전용 SQL 로그인을 사용할 수 있습니까? 표준 DBContext EF를 사용하면 쿼리 코드에 SaveChanges ()가 포함되지 않은 경우에도 CREATE TABLE 권한이 거부됩니다.
reachingnexus

2
그리고에서 그것을 상속하기IDisposable
hkarask

Set <>를 사용하는 대신 Query <>를 제안합니다. public IQueryable<TEntity> Get<TEntity>() where TEntity : class { return _dbContext.Query<TEntity>().AsNoTracking(); }
Allan Nielsen

@hkarask-내가 그렇게 할 것인지 확실하지 않습니다. 이 호출은 DbContext를 생성하지 않았기 때문에 폐기해서는 안됩니다. 이로 인해 나중에 버그를 추적하기가 어려울 수 있습니다.
Allan Nielsen

@AllanNielsen Query <>는 더 이상 사용되지 않는 것으로 표시됩니다. 그것에 따르면 Set <>를 사용해야합니다.
Frank
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.