Monthly Archives: Mayıs 2014

“Request entity is too large.” konusu

Eğer siz de “The page was not displayed because the request entity is too large.” hatası alıyorsanız, öyle internette her bulduğunuz şeyi denemeyin bazen bulduğunuz çözüm, çözüm olmayabilir. Bu konuyu çok uzatmayacağım ki kısaca çözüme geçelim.

Olay

SSL kullandığınız projelerinizin requestlerinin boyutları IIS’in applicationhost.config ayarı ile çatışması. Bu boyutun arttırılması, dosya yüklerken ya da büyük resultlar dönerken tip tip hatalar görmeniz tamamen buna delalettir.

Çözüm

Önce C:WindowsSystem32inetsrv adresine girip applicationhost.config dosyasının bir yedeğini aldın ki diliniz yanmasın. Sonra nette bulduğunuz klasik örneği kullanarak arttırım yapmayın, önce bir bakın adamlar ne yapmış örneklerinde;

appcmd set config "https://mysite" /section:system.webserver/serverruntime /uploadreadaheadsize:1048576 /commit:apphost demişler. Bi bakalım sırayla;

  • https://mysite buraya kendi sitenizin adını yazın, bu ad nedir diyorsanız hiç sitenin urlsini yazmayın, IIS’i açıp Sites kısmındaki ismini yazın arkadaşın…
  • 1048576 hep buradan yanıyor başımız. 1048576 = 1024 * 1024 = 1mb yani adam 1mb için örnek yazmış, sen de git kopyala hemen mal gibi, yapmayın tabii böyle. Max: 2147483647 verin ki bu da 1.99GB’a denktir.

Sonuç

Yükleme kısmınız varsa bu sorunu çözüyor bir de limiti 2gb’a kadar çıkartıyorsunuz da, 2GB’dan daha fazla yükleme yapmak için ayarlar .Net’de gelmiş olsa da IIS’de henüz gelmediğinden, 2GB’dan fazla doküman yükleyecekseniz, beklemeniz gerekmektedir.

Unit of Work Pattern

Uzundur yazılım tasarım kalıpları hakkında yazmayalı olmuştu. Bu sefer size benim de çok işime yarayan ve büyük üstan Martin Fowler tarafından bize yönlendirilen – aslında tam kaynağı konusunda tam bir fikrim yok ama Fowler’ın PoEAA1 kitabında bahsi geçmekte – bir pattern.

Bu tasarım kalıbının amacı ve uygulaması çok basit, bu yüzden projelerimde kullanmaya özen gösteriyorum, aslında basit bir sorunu gidermesine rağmen uygulama açısından çok büyük bir amaca hizmet etmekte. Sonuçta tasarım kalıbı dediğimiz şeyler de kusura bakmayın gereksiz şeyler değiller.

Nedir, Amacı, Katmanı

Çok basit bir amacı var;

Veritabanında yapılan tüm işlemlerin tek bir bağlantı üzerinden yürümesi ve bir yerde hafızada tutulması.

Farkına vardığınız gibi bu bir DAL (Data Access Layer) kalıbı. Adından da anlaşılabileceği gibi her yapılan işlemin bir işlem birimi (unit of work) olarak ele alınmasını, bunların saklanmasını ele alan sınıf. Daha sonrasında bu işlemlerin toplu olarak kaydedilmesini (Save), geri alınmasını (Rollback), ya da iptal edilmesini (Dispose) sağlamaktadır. Detaylı açıklamayı Unit of Work Design Pattern makalesinde bulabilirsiniz.

Kullanımı

Kullanımı için çoğu kaynak Repository Pattern (Depolama tasarım kalıbı) kullanılmasını önermektedir. Aksine bir repository nesnesine ihtiyacınız yoktur. Her hangi bir bağlantı için, gerekli işlemleri içeren bir Unit of Work yazılabilir. Hiç de zor değil sonuçta. Ama tam olarak nasıl yazılması gerektiğini anlatayım.

Öncelikle elinizin altında, DAL için yazılmış bir data işlemleri nesnesi olmalı. Bu Repository Pattern olur, Generic Repository Pattern olur ya da CRUD işlemlerinin toplandığı bir sınıf olabilir. Bu sınıfın temel bağlantı alan yerini, dışarıdan bir kaynaktan alacak şekilde ayarlarsanız işlemlerimiz neredeyse tamamlanmış olur. Esas kafa karıştıran noktaları özetlersek;

  • Bağlantı dışarıdan, içerideki CRUD işlemi yapan sınıfa girmeli,
  • CRUD işlemi yapan sınıf kaydetme işlemlerini anlık olarak yapmamalı, kendi içinde Commit yapacak bir fonksiyon kullanmalı ve bu fonksiyon çağırılmadan işlem yapmamalı,
  • Transaction kullanılacaksa Rollback işlemleri için gerekli fonksiyonları içermeli,
  • CRUD fonksiyonlarını içeren sınıflar birden fazla olabilirler ki olmaları her zaman tercih edilendir.

Repository Pattern ile yazılmış sınıflar otomatikman Unit of Work için uygun olduğundan bu örneklerin hepsi onun üzerinden veriliyor. Fakat elinizde yukarıda yazdığım dört özelliğe sahip bir nesneniz varsa – teorik olarak zaten bu da repository pattern kullanmanızı sağlar fakat isminde repository yazmıyor diye kabul etmeyen arkadaşlarınız olabilir, oluyor öyle – siz de gayet Unit of Work kullanabilirsiniz.

Mimarisi

Basitçe yapılacak işlemi anlatayım; Tüm data işlemi yapan sınıflarınız Unit of Work içerisinde birer property olarak tutulur. Bu propertylere aynı DB connection ya da DB Context gönderilir. Property olarak gösterdiğimiz her sınıf kendi içinde değişmiş tüm datayı saklar. Unit of Work içinde bir “Save Changes” methodu olur. Bu method çağırıldığında tüm propertyler üzerindeki Save işlemleri çağırılır. Bu sayede işlemler yapılmış olur.

Avantaj olarak konuşursak, tüm DB işlemleri için dağıtık yapılarınızı tek bir sınıfta toplarsınız, transaction için rollback fonskiyonlarını ve kaydetme için save fonksiyonlarını tek bir method içinde kullanmış olursunuz. Bu da bir üst katman olan Service Layer ya da Business Intelligance Layer üzerinde işlem yaparken kolaylık sağlar. Eğer Dependency Injection kullanıyorsanız, küçük bir modifikasyonla hemen tüm DAL katmanınızı bu yapıya uygun hale getirebilirsiniz, zira çözülmesi gereken sadece DBContext nesnenizdir ve bu işlemlerin hepsi için sadece Unit of Work sınıfını güncellemeniz yeterli olacaktır. Ayrıca bir loglama yapısı kuracaksanız bunu da Unit of Work içerisine koyabilirsiniz. Hatta ve hatta DB’niz yoksa ve sadece XML işlemler yapıyorsanız, Service katmanının istediğiniz gibi yazılmasını ve dataların proje bitene kadar XML’de saklanmasını sağlayabilirsiniz. Anlat anlat bitmez bu işlemler, örneğe geçelim isterseniz.

Örnek

Bu kısımları internetten çok beğendiğim bir kaynaktan direk yapıştırıyorum, gerçi tüm örnekler aynı internette.

//IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
    IProductRepository ProductRepository { get; }
    IOrderRepository OrderRepository { get; }
    void Save();
    // Gerekiyorsa buraya RollBack eklenebilir...
}

//UnitOfWork.cs
public class UnitOfWork : IUnitOfWork
{
    private readonly MyDataContext _context; // En önemli yer burası!!!
    private IProductRepository productRepository;
    private IOrderRepository orderRepository;

    public UnitOfWork()
    {
        this._context = new MyDataContext();
    }

    public IProductRepository ProductRepository
    {
        get { return this.productRepository ?? (this.productRepository = new ProductRepository(_context)); }
    }

    public IOrderRepository OrderRepository
    {
        get { return this.orderRepository ?? (this.orderRepository = new OrderRepository(_context)); }
    }

    public void Save()
    {
        _context.SaveChanges();
    }

    private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Bu arada service katmanında kullanımına gelirsek;

IUnitOfWork _uow = new UnitOfWork();
public void SaveProduct(Product _product)
{
    _uow.ProductRepository.Add(_product);
    _uow.Save();
}

Sonuç

Bu pattern’in kullanılması bu kadar basit, daha sonrasında ister Generic Repository kullanın, ister kendi “repository” nesnenizi içeren barklı bir bağlantı türünüzü kullanın fark etmeyecektir. En önemli noktanız her zaman MyDataContext kısmı olduğunu da aklınızdan çıkarmayın. Bir ara Generic Repository Pattern ile bu Unit of Work’ü nasıl genişleteceğinizi de anlatacağım. Boş vaktinizi iyi değerlendirmeniz dileğiyle. Ha bu arada tabii bir de Generic Unit of Work Pattern diye bir şey de var…


  1. Patterns of Enterprise Application Architecture (Martin Fowler)