Entity Framework Veri Bağlamını Salt Okunur yapma


112

Bir Entity Framework Data Context'i 3. parti eklentilere göstermem gerekiyor. Amaç, bu eklentilerin yalnızca veri almasına izin vermek ve ekleme, güncelleme veya silme veya başka herhangi bir veritabanı değiştirme komutunu yayınlamalarına izin vermemektir. Dolayısıyla, bir veri bağlamını veya varlığı salt okunur olarak nasıl yapabilirim.


3
Veritabanına yazma erişimi olmayan bir kullanıcıyla onlara bir bağlam verin.
vcsjones

Teşekkürler. Bir SQLite veritabanı kullanıyorum. Bir bağlantı dizesi seçeneği aracılığıyla salt okunur modda açılabileceğini öğrendim.
Harindaka

2
DbContextOnlara bir IQueryableveya birkaç tane vermeyin .
ta.speot .is

Yanıtlar:


178

Salt okunur bir kullanıcıyla bağlantı kurmanın yanı sıra, DbContext'inize yapabileceğiniz birkaç başka şey daha vardır.

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
'içeriden bir adam' olduğunuz belliydi :) - bu 'salt okunur' bir bağlantıdan çok daha ilginç
NSGaga-çoğunlukla etkin değil

6
Kullanmanın geç AsNoTracking()yükleme kullanmayı imkansız hale getireceğini unutmayın .
Tom Pažourek

@ TomPažourek Bunun doğru olup olmadığını bilmiyorum ... EF'nin hala tembel yükleme proxy'leri oluşturduğunu düşünüyorum, ancak kimlik çözümlemesi biraz garipleşebilir.
bricelam

3
Geçersiz kılmayı public override Task<int> SaveChangesAsync()da unutmayın .
Pete

7
Buna güvenmeyin, çünkü (context as IObjectContextAdapter).ObjectContext.SaveChanges()yine de işe yarayacak. En iyi seçenek, DbContext(string nameOrConnectionString);oluşturucuyu veritabanı oluşturma malzemeleri için bir okuma / yazma bağlantı dizesi ve daha sonra salt okunur bir bağlantı dizesi ile kullanmaktır.
Jürgen Steinblock

33

Kabul edilen cevabın aksine, miras yerine kompozisyonu tercih etmenin daha iyi olacağına inanıyorum . O zaman, bir istisna atmak için SaveChanges gibi yöntemleri tutmaya gerek kalmaz. Üstelik neden ilk etapta bu tür yöntemlere ihtiyacınız var? Bir sınıfı, yöntem listesine baktığında tüketicisinin aldanmayacağı şekilde tasarlamalısınız. Genel arabirim, sınıfın gerçek amacı ve hedefi ile uyumlu olmalıdır, ancak kabul edilen yanıtta SaveChanges'a sahip olmak, Bağlamın salt okunur olduğu anlamına gelmez.

CQRS modelinin Okuma tarafı gibi salt okunur bir bağlama sahip olmam gereken yerlerde , aşağıdaki uygulamayı kullanıyorum. Tüketicisine Sorgulama yeteneklerinden başka bir şey sağlamaz.

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'i kullanarak, yalnızca DbContext'in sorgulama yeteneklerine erişebilirsiniz. Diyelim ki Order adında bir varlığınız var, o zaman ReadOnlyDataContext örneğini aşağıdaki gibi kullanacaksınız.

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

Bu yöntem db_datareader only sql login kullanımına izin veriyor mu? Standart bir DBContext EF ile, sorgu kodum herhangi bir SaveChanges () içermese bile CREATE TABLE izni reddedildi.
reachingnexus

2
Ve miras IDisposable
almasını sağlayın

Set <> kullanmak yerine Query <> öneririm. public IQueryable<TEntity> Get<TEntity>() where TEntity : class { return _dbContext.Query<TEntity>().AsNoTracking(); }
Allan Nielsen

@hkarask - bunu yapacağımdan emin değilim. Bu çağrı DbContext'i yaratmadığından, onu elden çıkarmamalıdır. Bu, bazı hataları daha sonra bulmanın zor olmasına yol açabilir.
Allan Nielsen

@AllanNielsen Sorgusu <> kullanımdan kaldırıldı olarak işaretlendi. Buna göre Set <> kullanılmalıdır.
Frank
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.