') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - gorillapower/EntityFramework-Plus: Entity Framework Utilities | Bulk Operations | Batch Delete | Batch Update | Query Cache | Query Filter | Query Future | Query Include | Audit · GitHub
Skip to content

Latest commit

History

300 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Improve Entity Framework performance and overcome limitations with MUST-HAVE features

Library Powered By

This library is powered by Entity Framework Extensions

Entity Framework Extensions

Download

Full VersionNuGetNuGet Install
Z.EntityFramework.Plus.EFCoredownloadPM> Install-Package Z.EntityFramework.Plus.EFCore
Z.EntityFramework.Plus.EF6downloadPM> Install-Package Z.EntityFramework.Plus.EF6
Z.EntityFramework.Plus.EF5downloadPM> Install-Package Z.EntityFramework.Plus.EF5

More download options (Full and Standalone Version)

Stay updated with latest changes

Twitter FollowFacebook Like

Features


Bulk Operations only available with Entity Framework Extensions

  • BulkSaveChanges
  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

Batch Delete

Deletes multiples rows in a single database roundtrip and without loading entities in the context.

// using Z.EntityFramework.Plus; // Don't forget to include this.// DELETE all users which has been inactive for 2 yearsctx.Users.Where(x =>x.LastLoginDate<DateTime.Now.AddYears(-2)).Delete();// DELETE using a BatchSizectx.Users.Where(x =>x.LastLoginDate<DateTime.Now.AddYears(-2)).Delete(x =>x.BatchSize=1000);

Support: EF5, EF6, EF Core

Learn more

Batch Update

Updates multiples rows using an expression in a single database roundtrip and without loading entities in the context.

// using Z.EntityFramework.Plus; // Don't forget to include this.// UPDATE all users which has been inactive for 2 yearsctx.Users.Where(x =>x.LastLoginDate<DateTime.Now.AddYears(-2)).Update(x =>newUser(){IsSoftDeleted=1});

Support: EF5, EF6, EF Core

Learn more

Query Cache

Query cache is the second level cache for Entity Framework.

The result of the query is returned from the cache. If the query is not cached yet, the query is materialized and cached before being returned.

You can specify cache policy and cache tag to control CacheItem expiration.

Support:

Cache Policy

// The query is cached using default QueryCacheManager optionsvarcountries=ctx.Countries.Where(x =>x.IsActive).FromCache();// (EF5 | EF6) The query is cached for 2 hoursvarstates=ctx.States.Where(x =>x.IsActive).FromCache(DateTime.Now.AddHours(2));// (EF7) The query is cached for 2 hours without any activityvaroptions=newMemoryCacheEntryOptions(){SlidingExpiration=TimeSpan.FromHours(2)};varstates=ctx.States.Where(x =>x.IsActive).FromCache(options);

Cache Tags

varstates=db.States.Where(x =>x.IsActive).FromCache("countries","states");varstateCount=db.States.Where(x =>x.IsActive).DeferredCount().FromCache("countries","states");// Expire all cache entry using the "countries" tagQueryCacheManager.ExpireTag("countries");

Support: EF5, EF6, EF Core

Learn more

Query Deferred

Defer the execution of a query which is normally executed to allow some features like Query Cache and Query Future.

// Oops! The query is already executed, we cannot use Query Cache or Query Future featuresvarcount=ctx.Customers.Count();// Query Cachectx.Customers.DeferredCount().FromCache();// Query Futurectx.Customers.DeferredCount().FutureValue();

All LINQ extensions are supported: Count, First, FirstOrDefault, Sum, etc.

Support: EF5, EF6, EF Core

Learn more

Query Filter

Filter query with predicate at global, instance or query level.

Support:

Global Filter

// CREATE global filterQueryFilterManager.Filter<Customer>(x =>x.Where(c =>c.IsActive));varctx=newEntityContext();// TIP: Add this line in EntitiesContext constructor insteadQueryFilterManager.InitilizeGlobalFilter(ctx);// SELECT * FROM Customer WHERE IsActive = truevarcustomer=ctx.Customers.ToList();

Instance Filter

varctx=newEntityContext();// CREATE filterctx.Filter<Customer>(x =>x.Where(c =>c.IsActive));// SELECT * FROM Customer WHERE IsActive = truevarcustomer=ctx.Customers.ToList();

Query Filter

varctx=newEntityContext();// CREATE filter disabledctx.Filter<Customer>(CustomEnum.EnumValue, x =>x.Where(c =>c.IsActive),false);// SELECT * FROM Customer WHERE IsActive = truevarcustomer=ctx.Customers.Filter(CustomEnum.EnumValue).ToList();

Support: EF5, EF6, EF Core

Learn more

Query Future

Query Future allow to reduce database roundtrip by batching multiple queries in the same sql command.

All future query are stored in a pending list. When the first future query require a database roundtrip, all query are resolved in the same sql command instead of making a database roundtrip for every sql command.

Support:

Future

// GET the states & countries listvarfutureCountries=db.Countries.Where(x =>x.IsActive).Future();varfutureStates=db.States.Where(x =>x.IsActive).Future();// TRIGGER all pending queries (futureCountries & futureStates)varcountries=futureCountries.ToList();

FutureValue

// GET the first active customer and the number of avtive customersvarfutureFirstCustomer=db.Customers.Where(x =>x.IsActive).DeferredFirstOrDefault().FutureValue();varfutureCustomerCount=db.Customers.Where(x =>x.IsActive).DeferredCount().FutureValue();// TRIGGER all pending queries (futureFirstCustomer & futureCustomerCount)CustomerfirstCustomer=futureFirstCustomer.Value;

Support: EF5, EF6, EF Core

Learn more

Query IncludeFilter

Entity Framework already support eager loading however the major drawback is you cannot control what will be included. There is no way to load only active item or load only the first 10 comments.

EF+ Query Include make it easy:

varctx=newEntityContext();// Load only active commentsvarposts=ctx.Post.IncludeFilter(x =>x.Comments.Where(x =>x.IsActive));

Support: EF6

Learn more

Query IncludeOptimized

Improve SQL generate by Include and filter child collections at the same times!

varctx=newEntityContext();// Load only active comments using an optimized includevarposts=ctx.Post.IncludeOptimized(x =>x.Comments.Where(x =>x.IsActive));

Support: EF5, EF6

Learn more

Audit

Allow to easily track changes, exclude/include entity or property and auto save audit entries in the database.

Support:

  • AutoSave Audit
  • Exclude & Include Entity
  • Exclude & Include Property
  • Format Value
  • Ignore Events
  • Property Unchanged
  • Soft Add & Soft Delete
// using Z.EntityFramework.Plus; // Don't forget to include this.varctx=newEntityContext();// ... ctx changes ...varaudit=newAudit();audit.CreatedBy="ZZZ Projects";// Optionalctx.SaveChanges(audit);// Access to all auditing informationvarentries=audit.Entries;foreach(varentryinentries){foreach(varpropertyinentry.Properties){}}

AutoSave audit in your database

AuditManager.DefaultConfiguration.AutoSavePreAction=(context,audit)=>(contextasEntityContext).AuditEntries.AddRange(audit.Entries);

Support: EF5, EF6, EF Core

Learn more

Contribute

The best way to contribute is by spreading the word about the library:

  • Blog it
  • Comment it
  • Fork it
  • Star it
  • Share it

A HUGE THANKS for your help.

More Projects

Entity Framework

Bulk Operations

Expression Evaluator

Utilities

Need more info?info@zzzprojects.com

Contact our outstanding customer support for any request. We usually answer within the next business day, hour, or minutes!

About

Entity Framework Utilities | Bulk Operations | Batch Delete | Batch Update | Query Cache | Query Filter | Query Future | Query Include | Audit

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages