ObjectRepository - NET in-memory repository pattern bakeng sa merero ea hau ea lapeng

Ke hobane'ng ha u boloka data eohle mohopolong?

Ho boloka sebaka sa marang-rang kapa data ea backend, takatso ea pele ea batho ba bangata ba hlaphohetsoeng kelellong e tla ba ho khetha database ea SQL. 

Empa ka linako tse ling ho na le mohopolo oa hore mohlala oa data ha o tšoanelehe bakeng sa SQL: ka mohlala, ha u haha ​​​​patlisiso kapa graph ea sechaba, u lokela ho batla likamano tse rarahaneng pakeng tsa lintho. 

Boemo bo bobe ka ho fetisisa ke ha o sebetsa sehlopheng mme mosebetsi-'moho a sa tsebe ho theha lipotso tse potlakileng. U qetile nako e kae u rarolla mathata a N+1 le ho haha ​​li-index tsa tlatsetso e le hore KHETHA leqepheng le ka sehloohong e tla qetella ka nako e lekaneng?

Mokhoa o mong o tsebahalang ke NoSQL. Lilemong tse 'maloa tse fetileng ho ne ho e-na le hype e ngata ho pota-pota sehlooho sena - bakeng sa ketsahalo efe kapa efe e loketseng ba ile ba sebelisa MongoDB mme ba thabela likarabo ka mokhoa oa litokomane tsa json. (ka tsela, ke lithupa tse kae tseo u lokelang ho li kenya ka lebaka la lihokelo tse chitja litokomaneng?).

Ke fana ka maikutlo a ho leka mokhoa o mong, o mong - ke hobane'ng ha u sa leke ho boloka lintlha tsohle mohopolong oa kopo, nako le nako u li boloke sebakeng sa polokelo e sa reroang (faele, database e hole)? 

Memori e se e le theko e tlase, 'me data efe kapa efe e ka bang teng bakeng sa merero e mengata e nyane le e mahareng e tla kena mohopolong oa 1 GB. (Mohlala, projeke eo ke e ratang haholo ea lapeng ke tracker ea lichelete, e bolokang lipalo-palo tsa letsatsi le letsatsi le nalane ea lits'enyehelo tsa ka, li-balance, le transactions bakeng sa selemo le halofo, e ja mohopolo oa 45 MB feela.)

Melemo:

  • Ho fumana lintlha ho ba bonolo - ha ho hlokahale hore u tšoenyehe ka lipotso, ho kenya botsoa, ​​likarolo tsa ORM, u sebetsa ka lintho tse tloaelehileng tsa C #;
  • Ha ho na mathata a amanang le phihlello ho tsoa likhoeleng tse fapaneng;
  • Ka potlako haholo - ha ho likopo tsa marang-rang, ha ho phetolelo ea khoutu puong ea lipotso, ha ho hlokahale (de) serialization ea lintho;
  • Hoa amoheleha ho boloka data ka mokhoa ofe kapa ofe - e ka ba ho XML ho disk, kapa SQL Server, kapa Azure Table Storage.

Chelete:

  • Sekala se otlolohileng se lahlehile, 'me ka lebaka leo, phepelo ea nako ea zero e ke ke ea etsoa;
  • Haeba sesebelisoa se senyeha, u ka lahleheloa ke data hanyane. (Empa kopo ea rona ha e so ka e senyeha, ho joalo?)

Hona e sebetsa?

Algorithm e tjena:

  • Qalong, khokahano e thehiloe le polokelo ea data, mme data e kentsoe;
  • Mohlala oa ntho, li-index tsa mantlha, le li-index tsa kamano (1:1, 1:Many) li hahiloe;
  • Ngoliso e etsoa bakeng sa liphetoho meahong ea ntho (INotifyPropertyChanged) le bakeng sa ho kenyelletsa kapa ho tlosa likarolo pokellong (INotifyCollectionChanged);
  • Ha ho ngolisoa ho qala, ntho e fetotsoeng e eketsoa moleng oa ho ngolla polokelong ea data;
  • Liphetoho tsa polokelo li bolokoa nako le nako (ka sebali) ka khoele e ka morao;
  • Ha o tsoa ts'ebetsong, liphetoho le tsona li bolokoa polokelong.

Khoutu Mohlala

Ho eketsa likarolo tse hlokahalang

// Основная библиотека
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

Re hlalosa mohlala oa data o tla bolokoa polokelong

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; }
}

Ebe mohlala oa ntho:

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;
}

Qetellong, sehlopha sa polokelo ka boeona bakeng sa ho fumana data:

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();
    }
}

Etsa mohlala oa ObjectRepository:

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

Haeba morero o tla sebelisa HangFire

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

Ho kenya ntho e ncha:

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

Ka pitso ena, ntho MotsoaliMohlala e kenyelelitsoe ho cache ea lehae le letoto la ho ngolla polokelongtshedimosetso. Ka hona, ts'ebetso ena e nka O (1), 'me ntho ena e ka sebetsoa hang-hang.

Mohlala, ho fumana ntho ena sebakeng sa polokelo le ho netefatsa hore ntho e khutlisitsoeng ke mohlala o ts'oanang:

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

Ho etsahalang? Beha () kgutlisetso TafoleDictionary, e nang le ConcurrentDictionary 'me e fana ka ts'ebetso e eketsehileng ea li-index tsa mathomo le tsa bobeli. Sena se o lumella ho ba le mekhoa ea ho batla ka Id (kapa li-index tse ling tsa mosebelisi) ntle le ho pheta-pheta lintho tsohle.

Ha o eketsa dintho ho ObjectRepository peeletso e eketsoa ho fetola thepa ea bona, kahoo phetoho efe kapa efe ea thepa e boetse e etsa hore ntho ena e eketsoe moleng oa ho ngola. 
Ho ntlafatsa thepa ho tsoa kantle ho shebahala ho tšoana le ho sebetsa le ntho ea POCO:

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

O ka hlakola ntho ka litsela tse latelang:

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

Sena se boetse se eketsa ntho moleng oa ho hlakola.

Ho boloka ho sebetsa joang?

ObjectRepository ha lintho tse shebiloeng li fetoha (ho eketsa kapa ho hlakola, kapa ho fetola thepa), ho hlahisa ketsahalo ModelChangedngolisitsoe ho Bobolokelo. Phethahatso Bobolokelo ha ketsahalo e etsahala ModelChanged Liphetoho li behiloe ka mela e 3 - bakeng sa ho eketsa, ho ntlafatsa, le ho hlakola.

Hape ts'ebetsong Bobolokelo ha ba qala, ba theha sebali sa nako se etsang hore liphetoho li bolokehe metsotsoana e meng le e meng e 5. 

Ntle le moo, ho na le API ea ho qobella mohala oa ho boloka: ObjectRepository.Boloka().

Pele ho poloko e 'ngoe le e' ngoe, lits'ebetso tse se nang moelelo li qala ho tlosoa meleng (mohlala, diketsahalo tse kopitsoang - ha ntho e fetotsoe habeli kapa lintho tse kentsoeng / ho tlosoa ka potlako), 'me feela ka mor'a moo ho ipoloka. 

Maemong 'ohle, ntho eohle ea hona joale e bolokiloe, kahoo ho ka etsahala hore lintho li bolokoe ka tatellano e fapaneng ho feta kamoo li fetotsoeng, ho kenyelletsa le liphetolelo tse ncha tsa lintho ho feta nakong eo li neng li kenngoa moleng.

Ho na le eng hape?

  • Lilaebrari tsohle li thehiloe ho .NET Standard 2.0. E ka sebelisoa morerong ofe kapa ofe oa sejoale-joale oa .NET.
  • API e bolokehile ka khoele. Lipokello tsa ka hare li kenngoa ts'ebetsong ho latela ConcurrentDictionary, ba sebetsanang le liketsahalo ba na le linotlolo kapa ha ba li hloke. 
    Ntho feela eo u lokelang ho e hopola ke ho letsetsa ObjectRepository.Boloka();
  • Li-index tse ikhethileng (li hloka bo ikhethang):

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

Ke mang ea e sebelisang?

Ka bonna, ke ile ka qala ho sebelisa mokhoa ona mererong eohle ea ho itlosa bolutu hobane e loketse ebile ha e hloke litšenyehelo tse kholo bakeng sa ho ngola lera la phihlello ea data kapa ho tsamaisa lisebelisoa tse boima. Ka bonna, ho boloka data ho litedb kapa faele hangata ho ntekane. 

Empa nakong e fetileng, ha EscapeTeams e seng e sa sebetse (Ke ne ke nahana hore ke ena, chelete - empa che, boiphihlelo hape) - e sebelisetsoang ho boloka data ho Azure Table Storage.

Merero ea bokamoso

Ke kopa ho lokisa e 'ngoe ea mathata a ka sehloohong a mokhoa ona - ho pharalla ka mokhoa o otlolohileng. Ho etsa sena, o hloka litšebelisano tse ajoang (sic!), Kapa u etse qeto e tiileng ea hore data e tšoanang e tsoang maemong a fapaneng ha ea lokela ho fetoha, kapa u e lumelle hore e fetohe ho latela molao-motheo o reng "ea ho qetela o nepile."

Ho ea ka pono ea tekheniki, ke bona morero o latelang kamoo ho ka khonehang:

  • Boloka EventLog le Snapshot ho fapana le mofuta oa ntho
  • Fumana maemo a mang (kenya liphetho tsa maemo ohle ho litlhophiso? udp discovery? master/slave?)
  • Iketsetse lipakeng tsa liketsahalo tsa EventLog ka algorithm efe kapa efe ea tumellano, joalo ka RAFT.

Hape ho na le bothata bo bong bo ntšoenyang - ho tlosoa ha cascade, kapa ho lemoha linyeoe tsa ho tlosoa ha lintho tse nang le lihokelo tse tsoang linthong tse ling. 

Khoutu ea mohloli

Haeba u balile ho fihla mona, se setseng ke ho bala khoutu; e ka fumanoa ho GitHub:
https://github.com/DiverOfDark/ObjectRepository

Source: www.habr.com

Eketsa ka tlhaloso