ObjectRepository - NET in-memory repository pattern yamapulojekiti anu akunyumba

Bwanji kusunga deta yonse mu kukumbukira?

Kusunga tsamba lawebusayiti kapena kubweza deta, chikhumbo choyamba cha anthu oganiza bwino chidzakhala kusankha database ya SQL. 

Koma nthawi zina malingaliro amabwera m'maganizo kuti chitsanzo cha deta sichiri choyenera kwa SQL: mwachitsanzo, pomanga kufufuza kapena graph ya chikhalidwe cha anthu, muyenera kufufuza maubwenzi ovuta pakati pa zinthu. 

Choipa kwambiri ndi pamene mumagwira ntchito mu gulu ndipo mnzanu sadziwa kupanga mafunso ofulumira. Kodi mwakhala nthawi yochuluka bwanji mukuthetsa mavuto a N+1 ndikupanga ma index owonjezera kuti ZOSAKHA patsamba lalikulu zimalize mu nthawi yokwanira?

Njira ina yotchuka ndi NoSQL. Zaka zingapo zapitazo panali chipwirikiti chambiri pamutuwu - nthawi iliyonse yabwino adatumiza MongoDB ndipo anali okondwa ndi mayankho ngati zolemba za json. (mwa njira, ndi ndodo zingati zomwe munayenera kuyika chifukwa cha maulalo ozungulira m'makalata?).

Ndikupangira kuyesa njira ina, njira ina - bwanji osayesa kusunga zidziwitso zonse pamakumbukiro a pulogalamuyo, ndikuzisunga nthawi ndi nthawi kusungirako mwachisawawa (fayilo, nkhokwe yakutali)? 

Memory yakhala yotsika mtengo, ndipo chilichonse chomwe chingatheke pama projekiti ang'onoang'ono ndi apakatikati chidzakwanira kukumbukira 1 GB. (Mwachitsanzo, pulojekiti yomwe ndimakonda yakunyumba ndi ndalama tracker, yomwe imasunga ziwerengero zatsiku ndi tsiku ndi mbiri ya ndalama zomwe ndimagwiritsa ntchito, zotsalira, ndi zogulira kwa chaka chimodzi ndi theka, zimangokumbukira 45 MB.)

Zotsatira:

  • Kupeza deta kumakhala kosavuta - simuyenera kuda nkhawa ndi mafunso, kutsitsa kwaulesi, mawonekedwe a ORM, mumagwira ntchito ndi zinthu za C # wamba;
  • Palibe mavuto okhudzana ndi kupeza kuchokera ku ulusi wosiyana;
  • Kuthamanga kwambiri - palibe zopempha zapaintaneti, palibe kumasulira kwa code m'chinenero cha funso, palibe chifukwa (de) serialization ya zinthu;
  • Ndizovomerezeka kusunga deta mwanjira iliyonse - zikhale mu XML pa disk, kapena mu SQL Server, kapena mu Azure Table Storage.

Wotsatsa:

  • Kukula kopingasa kumatayika, ndipo chifukwa chake, kuyimitsa kwa zero sikungachitike;
  • Ngati pulogalamuyo yawonongeka, mutha kutaya data pang'ono. (Koma ntchito yathu sichitha, sichoncho?)

Kodi ntchito?

Ma algorithm ndi awa:

  • Pachiyambi, kugwirizana kumakhazikitsidwa ndi kusungirako deta, ndipo deta imayikidwa;
  • Chitsanzo cha chinthu, ma index oyambira, ndi maulalo (1:1, 1:Ambiri) amapangidwa;
  • Kulembetsa kumapangidwira kusintha kwazinthu (INotifyPropertyChanged) komanso kuwonjezera kapena kuchotsa zinthu pazosonkhanitsira (INNotifyCollectionChanged);
  • Pamene kulembetsa kumayambika, chinthu chosinthidwa chikuwonjezeredwa pamzere wolembera kusungirako deta;
  • Zosintha pazosungira zimasungidwa nthawi ndi nthawi (pa timer) mu ulusi wakumbuyo;
  • Mukatuluka mu pulogalamuyi, zosintha zimasungidwanso kumalo osungira.

Kodi Chitsanzo

Kuwonjezera zofunikira zofunika

// Основная библиотека
Install-Package OutCode.EscapeTeams.ObjectRepository
    
// Хранилище данных, в котором будут сохраняться изменения
// Используйте то, которым будете пользоваться.
Install-Package OutCode.EscapeTeams.ObjectRepository.File
Install-Package OutCode.EscapeTeams.ObjectRepository.LiteDb
Install-Package OutCode.EscapeTeams.ObjectRepository.AzureTableStorage
    
// Опционально - если нужно хранить модель данных для Hangfire
// Install-Package OutCode.EscapeTeams.ObjectRepository.Hangfire

Timalongosola chitsanzo cha deta chomwe chidzasungidwa mu yosungirako

public class ParentEntity : BaseEntity
{
    public ParentEntity(Guid id) => Id = id;
}
    
public class ChildEntity : BaseEntity
{
    public ChildEntity(Guid id) => Id = id;
    public Guid ParentId { get; set; }
    public string Value { get; set; }
}

Kenako chinthu model:

public class ParentModel : ModelBase
{
    public ParentModel(ParentEntity entity)
    {
        Entity = entity;
    }
    
    public ParentModel()
    {
        Entity = new ParentEntity(Guid.NewGuid());
    }
    
    public Guid? NullableId => null;
    
    // Пример связи 1:Many
    public IEnumerable<ChildModel> Children => Multiple<ChildModel>(x => x.ParentId);
    
    protected override BaseEntity Entity { get; }
}
    
public class ChildModel : ModelBase
{
    private ChildEntity _childEntity;
    
    public ChildModel(ChildEntity entity)
    {
        _childEntity = entity;
    }
    
    public ChildModel() 
    {
        _childEntity = new ChildEntity(Guid.NewGuid());
    }
    
    public Guid ParentId
    {
        get => _childEntity.ParentId;
        set => UpdateProperty(() => _childEntity.ParentId, value);
    }
    
    public string Value
    {
        get => _childEntity.Value;
        set => UpdateProperty(() => _childEntity.Value, value
    }
    
    // Доступ с поиском по индексу
    public ParentModel Parent => Single<ParentModel>(ParentId);
    
    protected override BaseEntity Entity => _childEntity;
}

Ndipo potsiriza, kalasi yosungiramo palokha kuti mupeze deta:

public class MyObjectRepository : ObjectRepositoryBase
{
    public MyObjectRepository(IStorage storage) : base(storage, NullLogger.Instance)
    {
        IsReadOnly = true; // Для тестов, позволяет не сохранять изменения в базу
    
        AddType((ParentEntity x) => new ParentModel(x));
        AddType((ChildEntity x) => new ChildModel(x));
    
        // Если используется Hangfire и необходимо хранить модель данных для Hangfire в ObjectRepository
        // this.RegisterHangfireScheme(); 
    
        Initialize();
    }
}

Pangani chitsanzo cha ObjectRepository:

var memory = new MemoryStream();
var db = new LiteDatabase(memory);
var dbStorage = new LiteDbStorage(db);
    
var repository = new MyObjectRepository(dbStorage);
await repository.WaitForInitialize();

Ngati polojekiti idzagwiritsa ntchito HangFire

public void ConfigureServices(IServiceCollection services, ObjectRepository objectRepository)
{
    services.AddHangfire(s => s.UseHangfireStorage(objectRepository));
}

Kuyika chinthu chatsopano:

var newParent = new ParentModel()
repository.Add(newParent);

Ndi kuitana uku, chinthu ParentModel imawonjezedwa ku cache yakomweko komanso pamzere wolembera ku database. Choncho, opaleshoniyi imatenga O (1), ndipo chinthu ichi chikhoza kugwiritsidwa ntchito nthawi yomweyo.

Mwachitsanzo, kupeza chinthu ichi m'nkhokwe ndikutsimikizira kuti chinthu chomwe chabwezedwa ndichofanana:

var parents = repository.Set<ParentModel>();
var myParent = parents.Find(newParent.Id);
Assert.IsTrue(ReferenceEquals(myParent, newParent));

Chikuchitika ndi chiyani? Khalani () zobwerera TableDictionary, yomwe ili ndi ConcurrentDictionary ndipo imapereka magwiridwe antchito owonjezera a ma index a pulayimale ndi achiwiri. Izi zimakupatsani mwayi kuti mukhale ndi njira zofufuzira ndi Id (kapena ma index ena ogwiritsira ntchito) popanda kubwereza zinthu zonse.

Powonjezera zinthu ObjectRepository kulembetsa kumawonjezeredwa kuti asinthe katundu wawo, kotero kusintha kulikonse kwa katundu kumapangitsanso kuti chinthu ichi chiwonjezedwe pamzere wolembera. 
Kusintha katundu kuchokera kunja kumawoneka chimodzimodzi ndikugwira ntchito ndi chinthu cha POCO:

myParent.Children.First().Property = "Updated value";

Mukhoza kuchotsa chinthu m'njira zotsatirazi:

repository.Remove(myParent);
repository.RemoveRange(otherParents);
repository.Remove<ParentModel>(x => !x.Children.Any());

Izi zimawonjezeranso chinthucho pamzere wochotsa.

Kodi kupulumutsa kumagwira ntchito bwanji?

ObjectRepository pamene zinthu zoyang'aniridwa zikusintha (mwina kuwonjezera kapena kuchotsa, kapena kusintha katundu), zimadzutsa chochitika ModelChangedadalembetsa ku Kusungirako. Kukhazikitsa Kusungirako pamene chochitika chikuchitika ModelChanged zosintha zimayikidwa m'mizere itatu - pakuwonjezera, kukonzanso, ndi kufufuta.

Komanso kukhazikitsa Kusungirako poyambitsa, amapanga chowerengera chomwe chimapangitsa kuti kusintha kusungidwe masekondi 5 aliwonse. 

Kuphatikiza apo, pali API yokakamiza kuyimba foni: ObjectRepository.Sungani().

Pambuyo pa kupulumutsa kulikonse, ntchito zopanda tanthauzo zimachotsedwa koyamba pamizere (mwachitsanzo, zochitika zobwerezabwereza - pamene chinthu chinasinthidwa kawiri kapena mwamsanga kuwonjezeredwa / kuchotsedwa zinthu), ndiyeno pokha pokha kudzipulumutsa. 

Muzochitika zonse, chinthu chonse chamakono chimasungidwa, kotero ndizotheka kuti zinthu zimasungidwa mosiyana ndi momwe zinasinthidwira, kuphatikizapo mitundu yatsopano ya zinthu kusiyana ndi nthawi yomwe adawonjezeredwa pamzere.

Ndi chiyani chinanso?

  • Malaibulale onse adakhazikitsidwa pa NET Standard 2.0. Itha kugwiritsidwa ntchito muntchito iliyonse yamakono ya .NET.
  • API ndiyotetezedwa ku ulusi. Zosonkhanitsa zamkati zimakhazikitsidwa potengera ConcurrentDictionary, oyang'anira zochitika amakhala ndi maloko kapena sakuwafuna. 
    Chinthu chokha choyenera kukumbukira ndikuyimba foni ObjectRepository.Sungani ();
  • Zolozera mokhazikika (zimafunika zapadera):

repository.Set<ChildModel>().AddIndex(x => x.Value);
repository.Set<ChildModel>().Find(x => x.Value, "myValue");

Ndani amachigwiritsa ntchito?

Ineyo pandekha, ndinayamba kugwiritsa ntchito njirayi m'mapulojekiti onse osangalatsa chifukwa ndi yabwino ndipo safuna ndalama zambiri polemba kusanjikiza kwa data kapena kuyika zida zolemetsa. Payekha, kusunga deta mu litedb kapena fayilo nthawi zambiri kumakhala kokwanira kwa ine. 

Koma m'mbuyomu, pomwe EscapeTeams yomwe yatsala pang'ono kutha (Ndinaganiza kuti apa, ndalama - koma ayi, zinachitikiranso) - amagwiritsidwa ntchito kusunga deta mu Azure Table Storage.

Zimakonzekera zam'tsogolo

Ndikufuna kukonza chimodzi mwazovuta zazikulu za njirayi - makulitsidwe opingasa. Kuti muchite izi, mufunika kugawidwa (sic!), Kapena kupanga chisankho champhamvu kuti deta yomweyi kuchokera ku zochitika zosiyanasiyana zisasinthe, kapena kuwalola kuti asinthe malinga ndi mfundo yakuti "yemwe ali wotsiriza ali wolondola."

Kuchokera pamalingaliro aukadaulo, ndikuwona chiwembu chotsatirachi momwe ndingathere:

  • Sungani EventLog ndi Snapshot m'malo mwachitsanzo cha chinthu
  • Pezani zina (onjezani malekezero a zochitika zonse pazokonda? udp discovery? master/slave?)
  • Fananizani pakati pa zochitika za EventLog kudzera mu algorithm yogwirizana, monga RAFT.

Palinso vuto lina lomwe limandidetsa nkhawa - kuchotsedwa kwa cascade, kapena kuzindikira milandu yochotsa zinthu zomwe zili ndi maulalo kuchokera kuzinthu zina. 

Nambala yachinsinsi

Ngati mwawerenga mpaka pano, ndiye kuti zonse zomwe zatsala ndikuwerenga nambala; zitha kupezeka pa GitHub:
https://github.com/DiverOfDark/ObjectRepository

Source: www.habr.com

Kuwonjezera ndemanga