Ana içeriğe atla

Serenity Hizmet Davranışlarını Kullanma

 Bu çok kiracılı sistemi Northwind'deki diğer tablolara genişletmek istersek, Roller ile yaptığımız adımların aynısını tekrarlarız. 

Çok zor görünmese de, çok fazla manuel çalışma gerektiriyor.

Serenity, Oluşturma, Güncelleme, Alma, Listeleme, Silme işleyicilerini engellemenize ve bunlara özel kod eklemenize olanak tanıyan hizmet davranışı sistemi sağlar.

Bu işleyicilerdeki yakalama günlüğü, benzersiz kısıtlama doğrulama vb. gibi bazı işlemler zaten hizmet davranışları olarak uygulanmıştır.

Davranışlar tüm satırlar için veya belirli bir özelliğe veya arayüze sahip olmak gibi bazı kurallara dayalı olarak etkinleştirilebilir. 

Örneğin CaptureLogBehavior, [CaptureLog] özelliğine sahip satırlar için etkinleştirilir.

İlk önce yeni davranışımızı tetikleyecek IMultiTenantRow arayüzünü tanımlayacağız . 

Bu sınıfı TenantRow.cs'nin yanındaki IMultiTenantRow.cs dosyasına yerleştirin :

using Serenity.Data;

namespace MultiTenancy
{
    public interface IMultiTenantRow
    {
        Int32Field TenantIdField { get; }
    }
}

Bunun yerine bu davranışı MultiTenantBehavior.cs dosyasına yanına ekleyin:

using MultiTenancy.Administration;
using Serenity;
using Serenity.Data;
using Serenity.Services;

namespace MultiTenancy
{
    public class MultiTenantBehavior : IImplicitBehavior,
        ISaveBehavior, IDeleteBehavior,
        IListBehavior, IRetrieveBehavior
    {
        private Int32Field fldTenantId;

        public bool ActivateFor(IRow row)
        {
            if (row is not IMultiTenantRow mt)
                return false;

            fldTenantId = mt.TenantIdField;
            return true;
        }

        public void OnPrepareQuery(IRetrieveRequestHandler handler,
            SqlQuery query)
        {
            if (!handler.Context.Permissions.HasPermission(PermissionKeys.Tenants))
                query.Where(fldTenantId == handler.Context.User.GetTenantId());
        }

        public void OnPrepareQuery(IListRequestHandler handler,
            SqlQuery query)
        {
            if (!handler.Context.Permissions.HasPermission(PermissionKeys.Tenants))
                query.Where(fldTenantId == handler.Context.User.GetTenantId());
        }

        public void OnSetInternalFields(ISaveRequestHandler handler)
        {
            if (handler.IsCreate)
                fldTenantId[handler.Row] = handler.Context.User.GetTenantId();
        }

        public void OnValidateRequest(ISaveRequestHandler handler)
        {
            if (handler.IsUpdate)
            {
                if (fldTenantId[handler.Old] != fldTenantId[handler.Row])
                    handler.Context.Permissions.ValidatePermission(PermissionKeys.Tenants, handler.Context.Localizer);
            }
        }

        public void OnValidateRequest(IDeleteRequestHandler handler)
        {
            if (fldTenantId[handler.Row] != handler.Context.User.GetTenantId())
                handler.Context.Permissions.ValidatePermission(PermissionKeys.Tenants, handler.Context.Localizer);
        }

        public void OnAfterDelete(IDeleteRequestHandler handler) { }
        public void OnAfterExecuteQuery(IRetrieveRequestHandler handler) { }
        public void OnAfterExecuteQuery(IListRequestHandler handler) { }
        public void OnAfterSave(ISaveRequestHandler handler) { }
        public void OnApplyFilters(IListRequestHandler handler, SqlQuery query) { }
        public void OnAudit(IDeleteRequestHandler handler) { }
        public void OnAudit(ISaveRequestHandler handler) { }
        public void OnBeforeDelete(IDeleteRequestHandler handler) { }
        public void OnBeforeExecuteQuery(IRetrieveRequestHandler handler) { }
        public void OnBeforeExecuteQuery(IListRequestHandler handler) { }
        public void OnBeforeSave(ISaveRequestHandler handler) { }
        public void OnPrepareQuery(IDeleteRequestHandler handler, SqlQuery query) { }
        public void OnPrepareQuery(ISaveRequestHandler handler, SqlQuery query) { }
        public void OnReturn(IDeleteRequestHandler handler) { }
        public void OnReturn(IRetrieveRequestHandler handler) { }
        public void OnReturn(IListRequestHandler handler) { }
        public void OnReturn(ISaveRequestHandler handler) { }
        public void OnValidateRequest(IRetrieveRequestHandler handler) { }
        public void OnValidateRequest(IListRequestHandler handler) { }
    }
}

IImplicitBehavior arayüzüne sahip davranış sınıfları, belirli bir satır türü için etkinleştirilip etkinleştirilmeyeceğine karar verir.

Bunu , istek işleyicileri tarafından çağrılan ActivateFor yöntemini uygulayarak yaparlar .

Bu yöntemde satır tipinin IMultiTenantRow arayüzünü uygulayıp uygulamadığını kontrol ediyoruz. Değilse, yalnızca false değerini döndürür.

Daha sonra TenantIdField'a daha sonra diğer yöntemlerde yeniden kullanmak için özel bir referans alırız .

ActivateFor her işleyici türü ve satır başına yalnızca bir kez çağrılır. 

Bu yöntem true değerini döndürürse davranış örneği, performans nedenleriyle agresif bir şekilde önbelleğe alınır ve bu satır ve işleyici türü için herhangi bir istek için yeniden kullanılır.

Bu nedenle, bir örnek tüm istekler tarafından paylaşıldığından, diğer yöntemlerde yazdığınız her şeyin iş parçacığı açısından güvenli olması gerekir.

Bir davranış, Retrieve , List , Save , Sil işleyicilerinden bir veya daha fazlasını engelleyebilir .

 Bunu IRetrieveBehavior , IListBehavior , ISaveBehavior veya IDeleteBehavior arayüzlerini uygulayarak yapar .

Burada tüm bu servis çağrılarını kesmemiz gerekiyor, bu yüzden tüm arayüzleri uyguluyoruz.

Sadece ilgilendiğimiz yöntemleri doldurup, diğerlerini boş bırakıyoruz.

Burada uyguladığımız yöntemler, önceki bölümde RoleRepository.cs'de geçersiz kıldığımız yöntemlere karşılık gelir. 

İçerdikleri kod hemen hemen aynıdır, ancak burada daha genel olmamız gerekir, çünkü bu davranış IMultiTenantRow uygulayan herhangi bir satır türü için işe yarayacaktır .

Davranışı Kullanarak Rol Deposunu Yeniden Uygulama

Şimdi RoleRepository.cs'de yaptığımız her değişikliği geri alın :

public class RoleSaveHandler : SaveRequestHandler<MyRow, MyRequest, MyResponse>, IRoleSaveHandler
{
    public RoleSaveHandler(IRequestContext context)
         : base(context)
    {
    }

    //removed methods we override

    //...
}

public class RoleDeleteHandler : DeleteRequestHandler<MyRow, MyRequest, MyResponse>, IRoleDeleteHandler
{
    public RoleDeleteHandler(IRequestContext context)
         : base(context)
    {
    }
}

public class RoleRetrieveHandler : RetrieveRequestHandler<MyRow, MyRequest, MyResponse>, IRoleRetrieveHandler
{
    public RoleRetrieveHandler(IRequestContext context)
         : base(context)
    {
    }
}

public class RoleListHandler : ListRequestHandler<MyRow, MyRequest, MyResponse>, IRoleListHandler
{
    public RoleListHandler(IRequestContext context)
         : base(context)
    {
    }
}

Ve IMultiTenantRow arayüzünü RoleRow'a ekleyin :

namespace MultiTenancy.Administration
{
    //...
    public sealed class RoleRow : Row<RoleRow.RowFields>, IIdRow, INameRow, IMultiTenantRow
    {
        //...
        public Int32Field TenantIdField
        {
            get => Fields.TenantId;
        }
        //...
    }
}

Bu blogdaki popüler yayınlar

Code generetor ile oluşturulan dosyaların açıklamaları

  1. Sunum (Presentation/UI) Katmanı (Kullanıcı arayüzü - HTML, TypeScript, Dialog, Grid) 🔹 XYZPage.ts 📌 Ne İşe Yarar? Kullanıcı arayüzünün TypeScript tarafındaki tanımıdır. Serenity'nin Dialog ve Grid bileşenlerini içeren bir TypeScript sınıfıdır. 📌 Çok Katmanlı Mimarideki Yeri: Sunum Katmanı (Presentation Layer) Kullanıcıdan veri almak ve göstermek için kullanılır. 🔹 XYZGrid.ts 📌 Ne İşe Yarar? Tablo (Grid) yapısını oluşturur ve verileri listeler. Filtreleme, sıralama ve sayfalama işlemleri için kullanılır. columnsKey ile hangi kolonların gösterileceğini belirler. 📌 Çok Katmanlı Mimarideki Yeri: Sunum Katmanı (Presentation Layer) Kullanıcının verileri listelediği ve etkileşimde bulunduğu yerdir. 🔹 XYZDialog.ts 📌 Ne İşe Yarar? CRUD (Create, Read, Update, Delete) işlemlerini yöneten pencere (modal) bileşeni Kullanıcı form aracılığıyla veri ekler, günceller veya siler. XYZForm.cs ile birlikte çalışır. 📌 Çok Katmanlı Mimarideki Yeri: Sunum Katmanı (Presentation Layer) Kull...

Serenity Web Nedir?

   Serenity  , açık kaynak teknolojileri üzerine kurulu bir ASP.NET Core/TypeScript uygulama platformudur. Standart kodlardan kaçınarak, tekrarlanan görevlere harcanan zamanı azaltarak ve en iyi yazılım tasarımı uygulamalarını uygulayarak bakım maliyetlerini düşürürken geliştirmeyi kolaylaştırmayı amaçlamaktadır. Serene  , Serenity platformunu temel alan ücretsiz, açık kaynaklı başlangıç ​​uygulama şablonumuzdur.  Bu dokümantasyon aracılığıyla eğitimimiz ve diğer örnekler için esas olarak Serene'yi kullanacağız. StartSharp  , ücretli müşterilerimize sunduğumuz premium uygulama şablonudur.  Daha gösterişli bir temaya ve bazı ekstra özelliklere  ek olarak Serene'deki her şeyi içerir  .  İkisi de Serenity platformunu temel alıyor. Adında Ne Var Serenity'nin sözlük anlamları  barış  ,  rahatlık  ve  sakinliktir  . Serenity ile bunu başarmaya çalışıyoruz.  Umarız yükledikten ve kullandıktan sonra siz de bu ş...