


Memperluas Ardalis.Spesifikasi untuk NHibernate dengan Linq, API Kriteria dan Pertanyaan Selesai
Ardalis.Specification ialah perpustakaan berkuasa yang membolehkan corak spesifikasi untuk pangkalan data pertanyaan, yang direka terutamanya untuk Teras Rangka Kerja Entiti, tetapi di sini saya akan menunjukkan cara anda boleh melanjutkan Ardalis.Specification untuk digunakan NHibernate sebagai ORM juga.
Siaran blog ini menganggap anda mempunyai sedikit pengalaman dengan Ardalis.Specification, dan ingin menggunakannya dalam projek menggunakan NHibernate. Jika anda belum biasa dengan Ardalis.Spesifikasi, pergi ke dokumentasi untuk mengetahui lebih lanjut.
Pertama, dalam NHibernate terdapat tiga cara terbina dalam yang berbeza untuk melakukan pertanyaan
- Linq untuk bertanya (menggunakan IQueryable)
- API Kriteria
- Pertanyaan Selesai
Saya akan menerangkan cara anda boleh melanjutkan Ardalis.Spesifikasi untuk mengendalikan kesemua 3 cara, tetapi memandangkan Linq kepada Query juga berfungsi dengan IQueryable seperti Teras Rangka Kerja Entiti, saya akan melalui pilihan itu dahulu.
Linq untuk bertanya
Terdapat sedikit nuansa antara Teras Rangka Kerja Entiti dan NHIbernate apabila ia datang untuk mewujudkan perhubungan gabungan. Dalam Teras Rangka Kerja Entiti kami mempunyai kaedah sambungan pada IQueryable: Include dan ThenInclude (ini juga merupakan nama kaedah yang digunakan dalam Ardalis.Specification).
Fetch, FetchMany, ThenFetch dan ThenFetchMany ialah kaedah khusus NHibernate pada IQueryable yang boleh bergabung. IEvaluator memberi kami kebolehlanjutan yang kami perlukan untuk menggunakan kaedah sambungan yang betul apabila kami bekerja dengan NHibernate.
Tambahkan pelaksanaan IEvaluator seperti berikut:
public class FetchEvaluator : IEvaluator { private static readonly MethodInfo FetchMethodInfo = typeof(EagerFetchingExtensionMethods) .GetTypeInfo().GetDeclaredMethods(nameof(EagerFetchingExtensionMethods.Fetch)) .Single(); private static readonly MethodInfo FetchManyMethodInfo = typeof(EagerFetchingExtensionMethods) .GetTypeInfo().GetDeclaredMethods(nameof(EagerFetchingExtensionMethods.FetchMany)) .Single(); private static readonly MethodInfo ThenFetchMethodInfo = typeof(EagerFetchingExtensionMethods) .GetTypeInfo().GetDeclaredMethods(nameof(EagerFetchingExtensionMethods.ThenFetch)) .Single(); private static readonly MethodInfo ThenFetchManyMethodInfo = typeof(EagerFetchingExtensionMethods) .GetTypeInfo().GetDeclaredMethods(nameof(EagerFetchingExtensionMethods.ThenFetchMany)) .Single(); public static FetchEvaluator Instance { get; } = new FetchEvaluator(); public IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> specification) where T : class { foreach (var includeInfo in specification.IncludeExpressions) { query = includeInfo.Type switch { IncludeTypeEnum.Include => BuildInclude<T>(query, includeInfo), IncludeTypeEnum.ThenInclude => BuildThenInclude<T>(query, includeInfo), _ => query }; } return query; } public bool IsCriteriaEvaluator { get; } = false; private IQueryable<T> BuildInclude<T>(IQueryable query, IncludeExpressionInfo includeInfo) { _ = includeInfo ?? throw new ArgumentNullException(nameof(includeInfo)); var methodInfo = (IsGenericEnumerable(includeInfo.PropertyType, out var propertyType) ? FetchManyMethodInfo : FetchMethodInfo); var method = methodInfo.MakeGenericMethod(includeInfo.EntityType, propertyType); var result = method.Invoke(null, new object[] { query, includeInfo.LambdaExpression }); _ = result ?? throw new TargetException(); return (IQueryable<T>)result; } private IQueryable<T> BuildThenInclude<T>(IQueryable query, IncludeExpressionInfo includeInfo) { _ = includeInfo ?? throw new ArgumentNullException(nameof(includeInfo)); _ = includeInfo.PreviousPropertyType ?? throw new ArgumentNullException(nameof(includeInfo.PreviousPropertyType)); var method = (IsGenericEnumerable(includeInfo.PreviousPropertyType, out var previousPropertyType) ? ThenFetchManyMethodInfo : ThenFetchMethodInfo); IsGenericEnumerable(includeInfo.PropertyType, out var propertyType); var result = method.MakeGenericMethod(includeInfo.EntityType, previousPropertyType, propertyType) .Invoke(null, new object[] { query, includeInfo.LambdaExpression }); _ = result ?? throw new TargetException(); return (IQueryable<T>)result; } private static bool IsGenericEnumerable(Type type, out Type propertyType) { if (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(IEnumerable<>))) { propertyType = type.GenericTypeArguments[0]; return true; } propertyType = type; return false; } }
Seterusnya kami perlu mengkonfigurasi ISpecificationEvaluator untuk menggunakan FetchEvaluator kami (dan penilai lain). Kami menambah ISpecificationEvaluator pelaksanaan seperti berikut dengan Penilai yang dikonfigurasikan dalam pembina. Di manaEvaluator, OrderEvaluator dan PenomboranEvaluator semuanya ada dalam Ardalis.Spesifikasi dan berfungsi dengan baik NHibernate juga.
public class LinqToQuerySpecificationEvaluator : ISpecificationEvaluator { private List<IEvaluator> Evaluators { get; } = new List<IEvaluator>(); public LinqToQuerySpecificationEvaluator() { Evaluators.AddRange(new IEvaluator[] { WhereEvaluator.Instance, OrderEvaluator.Instance, PaginationEvaluator.Instance, FetchEvaluator.Instance }); } public IQueryable<TResult> GetQuery<T, TResult>(IQueryable<T> query, ISpecification<T, TResult> specification) where T : class { if (specification is null) throw new ArgumentNullException(nameof(specification)); if (specification.Selector is null && specification.SelectorMany is null) throw new SelectorNotFoundException(); if (specification.Selector is not null && specification.SelectorMany is not null) throw new ConcurrentSelectorsException(); query = GetQuery(query, (ISpecification<T>)specification); return specification.Selector is not null ? query.Select(specification.Selector) : query.SelectMany(specification.SelectorMany!); } public IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> specification, bool evaluateCriteriaOnly = false) where T : class { if (specification is null) throw new ArgumentNullException(nameof(specification)); var evaluators = evaluateCriteriaOnly ? Evaluators.Where(x => x.IsCriteriaEvaluator) : Evaluators; foreach (var evaluator in evaluators) query = evaluator.GetQuery(query, specification); return query; } }
Kini kami boleh membuat rujukan kepada LinqToQuerySpecificationEvaluator dalam repositori kami yang mungkin kelihatan seperti ini:
public class Repository : IRepository { private readonly ISession _session; private readonly ISpecificationEvaluator _specificationEvaluator; public Repository(ISession session) { _session = session; _specificationEvaluator = new LinqToQuerySpecificationEvaluator(); } ... other repository methods public IEnumerable<T> List<T>(ISpecification<T> specification) where T : class { return _specificationEvaluator.GetQuery(_session.Query<T>().AsQueryable(), specification).ToList(); } public IEnumerable<TResult> List<T, TResult>(ISpecification<T, TResult> specification) where T : class { return _specificationEvaluator.GetQuery(_session.Query<T>().AsQueryable(), specification).ToList(); } public void Dispose() { _session.Dispose(); } }
Itu sahaja. Kami kini boleh menggunakan Linq untuk Pertanyaan dalam spesifikasi kami seperti yang biasa kami lakukan dengan Ardalis. Spesifikasi:
public class TrackByName : Specification<Core.Entitites.Track> { public TrackByName(string trackName) { Query.Where(x => x.Name == trackName); } }
Sekarang kita telah membincangkan pertanyaan berasaskan Linq, mari kita teruskan untuk mengendalikan API Kriteria dan Pertanyaan Selesai, yang memerlukan pendekatan berbeza.
Mencampurkan Linq, Kriteria dan Pertanyaan Dalam NHibernate
Memandangkan Criteria API dan Query Over mempunyai pelaksanaannya sendiri untuk menjana SQL, dan tidak menggunakan IQueryable, ia tidak serasi dengan antara muka IEvaluator. Penyelesaian saya adalah untuk mengelak daripada menggunakan antara muka IEvaluator untuk kaedah ini dalam kes ini, tetapi lebih fokus pada faedah corak spesifikasi. Tapi nak jugak boleh campur
Linq kepada Pertanyaan, Kriteria dan Pertanyaan Selesaikan dengan dalam penyelesaian saya (jika anda hanya memerlukan salah satu pelaksanaan ini, anda boleh memilih untuk keperluan terbaik anda).
Untuk dapat melakukannya, saya menambah empat kelas baharu yang mewarisi Spesifikasi atau Spesifikasi
NOTA: Himpunan tempat anda mentakrifkan kelas ini memerlukan rujukan kepada NHibernate semasa kami mentakrifkan tindakan untuk Kriteria dan QueryOver, yang boleh didapati dalam NHibernate
public class CriteriaSpecification<T> : Specification<T> { private Action<ICriteria>? _action; public Action<ICriteria> GetCriteria() => _action ?? throw new NotSupportedException("The criteria has not been specified. Please use UseCriteria() to define the criteria."); protected void UseCriteria(Action<ICriteria> action) => _action = action; } public class CriteriaSpecification<T, TResult> : Specification<T, TResult> { private Action<ICriteria>? _action; public Action<ICriteria> GetCriteria() => _action ?? throw new NotSupportedException("The criteria has not been specified. Please use UseCriteria() to define the criteria."); protected void UseCriteria(Action<ICriteria> action) => _action = action; } public class QueryOverSpecification<T> : Specification<T> { private Action<IQueryOver<T, T>>? _action; public Action<IQueryOver<T, T>> GetQueryOver() => _action ?? throw new NotSupportedException("The Query over has not been specified. Please use the UseQueryOver() to define the query over."); protected void UseQueryOver(Action<IQueryOver<T, T>> action) => _action = action; } public class QueryOverSpecification<T, TResult> : Specification<T, TResult> { private Func<IQueryOver<T, T>, IQueryOver<T, T>>? _action; public Func<IQueryOver<T, T>, IQueryOver<T, T>> GetQueryOver() => _action ?? throw new NotSupportedException("The Query over has not been specified. Please use the UseQueryOver() to define the query over."); protected void UseQueryOver(Func<IQueryOver<T, T>, IQueryOver<T, T>> action) => _action = action; }
Kemudian kami boleh menggunakan padanan corak dalam repositori kami untuk menukar cara kami melakukan pertanyaan dengan NHibernate
public IEnumerable<T> List<T>(ISpecification<T> specification) where T : class { return specification switch { CriteriaSpecification<T> criteriaSpecification => _session.CreateCriteria<T>() .Apply(query => criteriaSpecification.GetCriteria().Invoke(query)) .List<T>(), QueryOverSpecification<T> queryOverSpecification => _session.QueryOver<T>() .Apply(queryOver => queryOverSpecification.GetQueryOver().Invoke(queryOver)) .List<T>(), _ => _specificationEvaluator.GetQuery(_session.Query<T>().AsQueryable(), specification).ToList() }; } public IEnumerable<TResult> List<T, TResult>(ISpecification<T, TResult> specification) where T : class { return specification switch { CriteriaSpecification<T, TResult> criteriaSpecification => _session.CreateCriteria<T>() .Apply(query => criteriaSpecification.GetCriteria().Invoke(query)) .List<TResult>(), QueryOverSpecification<T, TResult> queryOverSpecification => _session.QueryOver<T>() .Apply(queryOver => queryOverSpecification.GetQueryOver().Invoke(queryOver)) .List<TResult>(), _ => _specificationEvaluator.GetQuery(_session.Query<T>().AsQueryable(), specification).ToList() }; }
Kaedah Apply() di atas ialah kaedah sambungan yang memudahkan pertanyaan kepada satu baris:
public static class QueryExtensions { public static T Apply<T>(this T obj, Action<T> action) { action(obj); return obj; } public static TResult Apply<T, TResult>(this T obj, Func<T, TResult> func) { return func(obj); } }
Contoh spesifikasi kriteria
NOTA: Himpunan tempat anda mentakrifkan kelas ini memerlukan rujukan kepada NHibernate semasa kami mentakrifkan tindakan untuk Kriteria, yang boleh didapati dalam NHibernate
public class TrackByNameCriteria : CriteriaSpecification<Track> { public TrackByNameCriteria(string trackName) { this.UseCriteria(criteria => criteria.Add(Restrictions.Eq(nameof(Track.Name), trackName))); } }
Contoh soal spesifikasi
NOTA: Himpunan tempat anda mentakrifkan kelas ini memerlukan rujukan kepada NHibernate semasa kami mentakrifkan tindakan untuk QueryOver, yang boleh didapati dalam NHibernate
public class TrackByNameQueryOver : QueryOverSpecification<Track> { public TrackByNameQueryOver(string trackName) { this.UseQueryOver(queryOver => queryOver.Where(x => x.Name == trackName)); } }
Dengan melanjutkan Ardalis.Specification untuk NHibernate, kami membuka kunci keupayaan untuk menggunakan Linq kepada Query, Criteria API dan Query Over—semuanya dalam satu corak repositori. Pendekatan ini menawarkan penyelesaian yang sangat mudah disesuaikan dan berkuasa untuk pengguna NHibernate
Atas ialah kandungan terperinci Memperluas Ardalis.Spesifikasi untuk NHibernate dengan Linq, API Kriteria dan Pertanyaan Selesai. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











Sejarah dan evolusi C# dan C adalah unik, dan prospek masa depan juga berbeza. 1.C dicipta oleh BjarnestroustRup pada tahun 1983 untuk memperkenalkan pengaturcaraan berorientasikan objek ke dalam bahasa C. Proses evolusinya termasuk pelbagai standardisasi, seperti C 11 memperkenalkan kata kunci auto dan ekspresi Lambda, C 20 memperkenalkan konsep dan coroutin, dan akan memberi tumpuan kepada pengaturcaraan prestasi dan sistem pada masa akan datang. 2.C# telah dikeluarkan oleh Microsoft pada tahun 2000. Menggabungkan kelebihan C dan Java, evolusinya memberi tumpuan kepada kesederhanaan dan produktiviti. Sebagai contoh, C#2.0 memperkenalkan generik dan C#5.0 memperkenalkan pengaturcaraan tak segerak, yang akan memberi tumpuan kepada produktiviti pemaju dan pengkomputeran awan pada masa akan datang.

Terdapat perbezaan yang signifikan dalam lengkung pembelajaran C# dan C dan pengalaman pemaju. 1) Keluk pembelajaran C# agak rata dan sesuai untuk pembangunan pesat dan aplikasi peringkat perusahaan. 2) Keluk pembelajaran C adalah curam dan sesuai untuk senario kawalan berprestasi tinggi dan rendah.

Penggunaan analisis statik di C terutamanya termasuk menemui masalah pengurusan memori, memeriksa kesilapan logik kod, dan meningkatkan keselamatan kod. 1) Analisis statik dapat mengenal pasti masalah seperti kebocoran memori, siaran berganda, dan penunjuk yang tidak dikenali. 2) Ia dapat mengesan pembolehubah yang tidak digunakan, kod mati dan percanggahan logik. 3) Alat analisis statik seperti perlindungan dapat mengesan limpahan penampan, limpahan integer dan panggilan API yang tidak selamat untuk meningkatkan keselamatan kod.

C Berinteraksi dengan XML melalui perpustakaan pihak ketiga (seperti TinyXML, PugixML, Xerces-C). 1) Gunakan perpustakaan untuk menghuraikan fail XML dan menukarnya ke dalam struktur data C-diproses. 2) Apabila menjana XML, tukar struktur data C ke format XML. 3) Dalam aplikasi praktikal, XML sering digunakan untuk fail konfigurasi dan pertukaran data untuk meningkatkan kecekapan pembangunan.

Menggunakan perpustakaan Chrono di C membolehkan anda mengawal selang masa dan masa dengan lebih tepat. Mari kita meneroka pesona perpustakaan ini. Perpustakaan Chrono C adalah sebahagian daripada Perpustakaan Standard, yang menyediakan cara moden untuk menangani selang waktu dan masa. Bagi pengaturcara yang telah menderita dari masa. H dan CTime, Chrono tidak diragukan lagi. Ia bukan sahaja meningkatkan kebolehbacaan dan mengekalkan kod, tetapi juga memberikan ketepatan dan fleksibiliti yang lebih tinggi. Mari kita mulakan dengan asas -asas. Perpustakaan Chrono terutamanya termasuk komponen utama berikut: STD :: Chrono :: System_Clock: Mewakili jam sistem, yang digunakan untuk mendapatkan masa semasa. Std :: Chron

Masa depan C akan memberi tumpuan kepada pengkomputeran selari, keselamatan, modularization dan pembelajaran AI/mesin: 1) Pengkomputeran selari akan dipertingkatkan melalui ciri -ciri seperti coroutine; 2) keselamatan akan diperbaiki melalui pemeriksaan jenis dan mekanisme pengurusan memori yang lebih ketat; 3) modulasi akan memudahkan organisasi dan penyusunan kod; 4) AI dan pembelajaran mesin akan mendorong C untuk menyesuaikan diri dengan keperluan baru, seperti pengkomputeran berangka dan sokongan pengaturcaraan GPU.

C isnotdying; it'sevolving.1) c suplemenvantduetoitsverversatilityandeficiencyinperformance-criticalapplications.2) thelanguageiscontinuouslyupdated, withc 20introducingfeatureslikemodulesandcoroutinestoMproveusability.3)

DMA di C merujuk kepada DirectMemoryAccess, teknologi akses memori langsung, yang membolehkan peranti perkakasan secara langsung menghantar data ke memori tanpa campur tangan CPU. 1) Operasi DMA sangat bergantung kepada peranti perkakasan dan pemacu, dan kaedah pelaksanaan berbeza dari sistem ke sistem. 2) Akses langsung ke memori boleh membawa risiko keselamatan, dan ketepatan dan keselamatan kod mesti dipastikan. 3) DMA boleh meningkatkan prestasi, tetapi penggunaan yang tidak wajar boleh menyebabkan kemerosotan prestasi sistem. Melalui amalan dan pembelajaran, kita dapat menguasai kemahiran menggunakan DMA dan memaksimumkan keberkesanannya dalam senario seperti penghantaran data berkelajuan tinggi dan pemprosesan isyarat masa nyata.
