• Stars
    star
    635
  • Rank 70,829 (Top 2 %)
  • Language
    C#
  • License
    Apache License 2.0
  • Created almost 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

EF Core Second Level Cache Interceptor

EF Core 3.1.x, 5x, 6x, 7x & 8x Second Level Cache Interceptor

GitHub Actions status

Second level caching is a query cache. The results of EF commands will be stored in the cache, so that the same EF commands will retrieve their data from the cache rather than executing them against the database again.

Install via NuGet

To install EFCoreSecondLevelCacheInterceptor, run the following command in the Package Manager Console:

Nuget

PM> Install-Package EFCoreSecondLevelCacheInterceptor

You can also view the package page on NuGet.

Usage (1 & 2 are mandatory)

1- Register a preferred cache provider:

Using the built-in In-Memory cache provider

performance

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        private readonly string _contentRootPath;

        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            _contentRootPath = env.ContentRootPath;
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")

            // Please use the `CacheManager.Core` or `EasyCaching.Redis` for the Redis cache provider.
            );

            var connectionString = Configuration["ConnectionStrings:ApplicationDbContextConnection"];
            if (connectionString.Contains("%CONTENTROOTPATH%"))
            {
                connectionString = connectionString.Replace("%CONTENTROOTPATH%", _contentRootPath);
            }
            services.AddConfiguredMsSqlDbContext(connectionString);

            services.AddControllersWithViews();
        }
    }
}

Using EasyCaching.Core as the cache provider

Here you can use the EasyCaching.Core, as a highly configurable cache manager too. To use its in-memory caching mechanism, add this entry to the .csproj file:

  <ItemGroup>
    <PackageReference Include="EasyCaching.InMemory" Version="1.6.1" />
  </ItemGroup>

Then register its required services:

namespace EFSecondLevelCache.Core.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            const string providerName1 = "InMemory1";
            services.AddEFSecondLevelCache(options =>
                    options.UseEasyCachingCoreProvider(providerName1, isHybridCache: false).DisableLogging(true).UseCacheKeyPrefix("EF_")
            );

            // Add an in-memory cache service provider
            // More info: https://easycaching.readthedocs.io/en/latest/In-Memory/
            services.AddEasyCaching(options =>
            {
                // use memory cache with your own configuration
                options.UseInMemory(config =>
                {
                    config.DBConfig = new InMemoryCachingOptions
                    {
                        // scan time, default value is 60s
                        ExpirationScanFrequency = 60,
                        // total count of cache items, default value is 10000
                        SizeLimit = 100,

                        // enable deep clone when reading object from cache or not, default value is true.
                        EnableReadDeepClone = false,
                        // enable deep clone when writing object to cache or not, default value is false.
                        EnableWriteDeepClone = false,
                    };
                    // the max random second will be added to cache's expiration, default value is 120
                    config.MaxRdSecond = 120;
                    // whether enable logging, default is false
                    config.EnableLogging = false;
                    // mutex key's alive time(ms), default is 5000
                    config.LockMs = 5000;
                    // when mutex key alive, it will sleep some time, default is 300
                    config.SleepMs = 300;
                }, providerName1);
            });
        }
    }
}

If you want to use the Redis as the preferred cache provider with EasyCaching.Core, first install the following package:

  <ItemGroup>
    <PackageReference Include="EasyCaching.Redis" Version="1.6.1" />
    <PackageReference Include="EasyCaching.Serialization.MessagePack" Version="1.6.1" />
  </ItemGroup>

And then register its required services:

namespace EFSecondLevelCache.Core.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            const string providerName1 = "Redis1";
            services.AddEFSecondLevelCache(options =>
                    options.UseEasyCachingCoreProvider(providerName1, isHybridCache: false).DisableLogging(true).UseCacheKeyPrefix("EF_")
            );

            // More info: https://easycaching.readthedocs.io/en/latest/Redis/
            services.AddEasyCaching(option =>
            {
                option.UseRedis(config =>
                {
                    config.DBConfig.AllowAdmin = true;
                    config.DBConfig.SyncTimeout = 10000;
                    config.DBConfig.AsyncTimeout = 10000;
                    config.DBConfig.Endpoints.Add(new EasyCaching.Core.Configurations.ServerEndPoint("127.0.0.1", 6379));
                    config.EnableLogging = true;
                    config.SerializerName = "Pack";
                    config.DBConfig.ConnectionTimeout = 10000;
                }, providerName1)
                .WithMessagePack(so =>
                                      {
                                         so.EnableCustomResolver = true;
                                         so.CustomResolvers = CompositeResolver.Create(
                                         new IMessagePackFormatter[]
                                         {
                                               DBNullFormatter.Instance, // This is necessary for the null values
                                         },
                                         new IFormatterResolver[]
                                         {
                                              NativeDateTimeResolver.Instance,
                                              ContractlessStandardResolver.Instance,
                                              StandardResolverAllowPrivate.Instance,
                                         });
                                       },
                                       "Pack");
            });
        }
    }
}

Using EasyCaching.Core as a dynamic cache provider

If you want to support multitenancy in your application and have a different Redis database per each tenant, first register multiple pre-configured providers with known providerNames and then select these providerNames based on the current tenant this way dynamically:

services.AddEFSecondLevelCache(options =>
    options.UseEasyCachingCoreProvider(
	   (serviceProvider, cacheKey) => "redis-db-" + serviceProvider.GetRequiredService<IHttpContextAccesor>().HttpContext.Request.Headers["tenant-id"],
	   isHybridCache: false)
	// `Or` you can set the cache key prefix per tenant dynamically  
	.UseCacheKeyPrefix(serviceProvider => "EF_" + serviceProvider.GetRequiredService<IHttpContextAccesor>().HttpContext.Request.Headers["tenant-id"])
	.DisableLogging(true)
	.UseCacheKeyPrefix("EF_")
);

Using CacheManager.Core as the cache provider [It's not actively maintained]

Also here you can use the CacheManager.Core, as a highly configurable cache manager too. To use its in-memory caching mechanism, add these entries to the .csproj file:

  <ItemGroup>
    <PackageReference Include="CacheManager.Core" Version="1.2.0" />
    <PackageReference Include="CacheManager.Microsoft.Extensions.Caching.Memory" Version="1.2.0" />
    <PackageReference Include="CacheManager.Serialization.Json" Version="1.2.0" />
  </ItemGroup>

Then register its required services:

namespace EFSecondLevelCache.Core.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
                options.UseCacheManagerCoreProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
            );

            // Add an in-memory cache service provider
            services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>));
            services.AddSingleton(typeof(ICacheManagerConfiguration),
                new CacheManager.Core.ConfigurationBuilder()
                        .WithJsonSerializer()
                        .WithMicrosoftMemoryCacheHandle(instanceName: "MemoryCache1")
                        .Build());
        }
    }
}

If you want to use the Redis as the preferred cache provider with CacheManager.Core, first install the CacheManager.StackExchange.Redis package and then register its required services:

// Add Redis cache service provider
var jss = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    TypeNameHandling = TypeNameHandling.Auto,
    Converters = { new SpecialTypesConverter() }
};

const string redisConfigurationKey = "redis";
services.AddSingleton(typeof(ICacheManagerConfiguration),
    new CacheManager.Core.ConfigurationBuilder()
        .WithJsonSerializer(serializationSettings: jss, deserializationSettings: jss)
        .WithUpdateMode(CacheUpdateMode.Up)
        .WithRedisConfiguration(redisConfigurationKey, config =>
        {
            config.WithAllowAdmin()
                .WithDatabase(0)
                .WithEndpoint("localhost", 6379)
                // Enables keyspace notifications to react on eviction/expiration of items.
                // Make sure that all servers are configured correctly and 'notify-keyspace-events' is at least set to 'Exe', otherwise CacheManager will not retrieve any events.
                // You can try 'Egx' or 'eA' value for the `notify-keyspace-events` too.
                // See https://redis.io/topics/notifications#configuration for configuration details.
                .EnableKeyspaceEvents();
        })
        .WithMaxRetries(100)
        .WithRetryTimeout(50)
        .WithRedisCacheHandle(redisConfigurationKey)
        .Build());
services.AddSingleton(typeof(ICacheManager<>), typeof(BaseCacheManager<>));

services.AddEFSecondLevelCache(options =>
    options.UseCacheManagerCoreProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
);

Here is the definition of the SpecialTypesConverter.

Using a custom cache provider

If you don't want to use the above cache providers, implement your custom IEFCacheServiceProvider and then introduce it using the options.UseCustomCacheProvider<T>() method.

2- Add SecondLevelCacheInterceptor to your DbContextOptionsBuilder pipeline:

    public static class MsSqlServiceCollectionExtensions
    {
        public static IServiceCollection AddConfiguredMsSqlDbContext(this IServiceCollection services, string connectionString)
        {
            services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) =>
                    optionsBuilder
                        .UseSqlServer(
                            connectionString,
                            sqlServerOptionsBuilder =>
                            {
                                sqlServerOptionsBuilder
                                    .CommandTimeout((int)TimeSpan.FromMinutes(3).TotalSeconds)
                                    .EnableRetryOnFailure()
                                    .MigrationsAssembly(typeof(MsSqlServiceCollectionExtensions).Assembly.FullName);
                            })
                        .AddInterceptors(serviceProvider.GetRequiredService<SecondLevelCacheInterceptor>()));
            return services;
        }
    }

Note: Some database providers don't support special fields such as DateTimeOffset, TimeSpan, etc. For these scenarios you will need the related converters.

3- Setting up the cache invalidation:

This library doesn't need any settings for the cache invalidation. It watches for all of the CRUD operations using its interceptor and then invalidates the related cache entries automatically. But if you want to invalidate the whole cache manually, inject the IEFCacheServiceProvider service and then call its _cacheServiceProvider.ClearAllCachedEntries() method or use it this way to specify the root cache keys which are a collection of a Prefix+TableName:

// Partial cache invalidation using the specified table names
// This is useful when you are monitoring your DB's changes using the SqlTableDependency
_cacheServiceProvider.InvalidateCacheDependencies(new EFCacheKey(new HashSet<string>()
{
   "EF_TableName1", // "EF_" is the cache key's prefix
   "EF_TableName2"
} {  KeyHash = "empty" }));

4- To cache the results of the normal queries like:

var post1 = context.Posts
                   .Where(x => x.Id > 0)
                   .OrderBy(x => x.Id)
                   .FirstOrDefault();

We can use the new Cacheable() extension method:

var post1 = context.Posts
                   .Where(x => x.Id > 0)
                   .OrderBy(x => x.Id)
                   .Cacheable(CacheExpirationMode.Sliding, TimeSpan.FromMinutes(5))
                   .FirstOrDefault();  // Async methods are supported too.

NOTE: It doesn't matter where the Cacheable method is located in this expression tree. It just adds the standard TagWith method to mark this query as Cacheable. Later SecondLevelCacheInterceptor will use this tag to identify the Cacheable queries.

Also it's possible to set the Cacheable() method's settings globally:

services.AddEFSecondLevelCache(options => options.UseMemoryCacheProvider(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(5)).DisableLogging(true).UseCacheKeyPrefix("EF_"));

In this case the above query will become:

var post1 = context.Posts
                   .Where(x => x.Id > 0)
                   .OrderBy(x => x.Id)
                   .Cacheable()
                   .FirstOrDefault();  // Async methods are supported too.

If you specify the settings of the Cacheable() method explicitly such as Cacheable(CacheExpirationMode.Sliding, TimeSpan.FromMinutes(5)), its setting will override the global setting.

Caching all of the queries

To cache all of the system's queries, just set the CacheAllQueries() method:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_");
                options.CacheAllQueries(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30));
            });

            // ...

This will put the whole system's queries in cache. In this case calling the Cacheable() methods won't be necessary. If you specify the Cacheable() method, its setting will override this global setting. If you want to exclude some of the queries from this global cache, apply the NotCacheable() method to them.

Caching some of the queries

To cache some of the system's queries based on their entity-types or table-names, use CacheQueriesContainingTypes or CacheQueriesContainingTableNames methods:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
                    /*.CacheQueriesContainingTypes(
                        CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30), TableTypeComparison.Contains,
                        typeof(Post), typeof(Product), typeof(User)
                        )*/
                    .CacheQueriesContainingTableNames(
                        CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30), TableNameComparison.ContainsOnly,
                        "posts", "products", "users"
                        );
            });

            // ...

This will put the the specified system's queries in cache. In this case calling the Cacheable() methods won't be necessary. If you specify the Cacheable() method, its setting will override this global setting. If you want to exclude some of the queries from this global cache, apply the NotCacheable() method to them.

Skip caching of some of the queries

To skip caching some of the system's queries based on their SQL commands, set the SkipCachingCommands predicate:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
                        // How to skip caching specific commands
                       .SkipCachingCommands(commandText =>
                                commandText.Contains("NEWID()", StringComparison.InvariantCultureIgnoreCase));
            });
            // ...

Skip caching of some of the queries based on their results

To skip caching some of the system's queries based on their results, set the SkipCachingResults predicate:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
                        // Don't cache null values. Remove this optional setting if it's not necessary.
                        .SkipCachingResults(result =>
                                result.Value == null || (result.Value is EFTableRows rows && rows.RowsCount == 0));
            });
            // ...

Skip caching some of the queries based on their table names

To do not cache some of the system's queries based on their entity-types or table-names, use CacheAllQueriesExceptContainingTypes or CacheAllQueriesExceptContainingTableNames methods:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
                    /*.CacheAllQueriesExceptContainingTypes(
                        CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30),
                        typeof(Post), typeof(Product), typeof(User)
                        )*/
                    .CacheAllQueriesExceptContainingTableNames(
                        CacheExpirationMode.Absolute, TimeSpan.FromMinutes(30),
                        "posts", "products", "users"
                        );
            });

            // ...

This will not put the the specified system's queries in cache. In this case calling the Cacheable() methods won't be necessary. If you specify the Cacheable() method, its setting will override this global setting.

Skip invalidating the related cache entries of a given query

Sometimes you don't want to invalidate the cache immediately, such when you are updating a post's likes or views count. In this case to skip invalidating the related cache entries of a given CRUD command, set the SkipCacheInvalidationCommands predicate:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseMemoryCacheProvider().DisableLogging(true).UseCacheKeyPrefix("EF_")
                    .SkipCacheInvalidationCommands(commandText =>
                                // How to skip invalidating the related cache entries of this query
                                commandText.Contains("NEWID()", StringComparison.InvariantCultureIgnoreCase));
            });
            // ...

Using a different hash provider

This library uses the XxHash64Unsafe class to calculate the hash of a query and its parameters to produce a corresponding cache-key. xxHash is an extremely fast non-cryptographic Hash algorithm. If you don't like it or you want to change it, just implement the IEFHashProvider interface and then introduce it this way:

namespace EFCoreSecondLevelCacheInterceptor.AspNetCoreSample
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddEFSecondLevelCache(options =>
            {
                options.UseCustomHashProvider<MyCustomHashProvider>();
                // ...                
            });

            // ...

Does it work?!

You should enable the logging system to see the behind the scene of the caching interceptor. First set the DisableLogging(false):

 services.AddEFSecondLevelCache(options =>
                options.UseMemoryCacheProvider().DisableLogging(false).UseCacheKeyPrefix("EF_")

And then change the log level to Debug in your appsettings.json file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Debug",
      "Microsoft": "Debug",
      "Microsoft.Hosting.Lifetime": "Debug"
    }
  }
}

Now after running a query multiple times, you should have these logged lines:

Suppressed result with a TableRows[ee20d2d7-ffc7-4ff9-9484-e8d4eecde53e] from the cache[KeyHash: EB153BD4, CacheDependencies: Page.].
Using the TableRows[ee20d2d7-ffc7-4ff9-9484-e8d4eecde53e] from the cache.

Notes:

  • Having the Suppressed the result with the TableRows message means the caching interceptor is working fine.
  • The next Executed DbCommand means nothing and it always will be logged by EF.
  • At the beginning there will be a lot of internal commands executed by the EF to run migrations, etc. Ignore these commands, because you will see the Suppressed the result with the TableRows messages for the frequently running queries.
  • Also you should verify it with a real DB profiler. It will log the 1st executed query and then on the 2nd run, you won't see it anymore.

Samples

Guidance

When to use

Good candidates for query caching are global site settings and public data, such as infrequently changing articles or comments. It can also be beneficial to cache data specific to a user so long as the cache expires frequently enough relative to the size of the user base that memory consumption remains acceptable. Small, per-user data that frequently exceeds the cache's lifetime, such as a user's photo path, is better held in user claims, which are stored in cookies, than in this cache.

Scope

This cache is scoped to the application, not the current user. It does not use session variables. Accordingly, when retrieving cached per-user data, be sure queries in include code such as .Where(x => .... && x.UserId == id).

Invalidation

This cache is updated when an entity is changed (insert, update, or delete) via a DbContext that uses this library. If the database is updated through some other means, such as a stored procedure or trigger, the cache becomes stale.

Transactions

To avoid complications, all of the queries inside an explicit transaction (context.Database.BeginTransaction()) will not be cached. But the cache invalidations due to its CRUD operations will occur. You can use .AllowCachingWithExplicitTransactions(true) setting to disable it.

More Repositories

1

iTextSharp.LGPLv2.Core

iTextSharp.LGPLv2.Core is an unofficial port of the last LGPL version of the iTextSharp (V4.1.6) to .NET Core
C#
551
star
2

EPPlus.Core

EPPlus.Core is an unofficial port of the EPPlus library to .NET Core
C#
369
star
3

PdfReport.Core

PdfReport.Core is a code first reporting engine, which is built on top of the iTextSharp.LGPLv2.Core and EPPlus.Core libraries
C#
350
star
4

EFSecondLevelCache.Core

Entity Framework Core Second Level Caching Library
C#
329
star
5

ASPNETCore2JwtAuthentication

Jwt Authentication without ASP.NET Core Identity
SCSS
298
star
6

OpenCVSharp-Samples

A collection of samples about using OpenCV in .NET applications.
C#
257
star
7

DNTPersianUtils.Core

DNTPersianUtils.Core is a collection of Persian helper extension methods
C#
236
star
8

DNTIdentity

A highly customized sample of the ASP.NET Core Identity
C#
232
star
9

DNTCaptcha.Core

DNTCaptcha.Core is a captcha generator and validator for ASP.NET Core applications
SCSS
205
star
10

GitHubFolderDownloader

It lets you to download a single folder of a repository without cloning or downloading the whole repository.
C#
164
star
11

Process-Proxifier

Using FiddlerCore to add proxy settings to the Windows applications
C#
151
star
12

DNTCommon.Web.Core

DNTCommon.Web.Core provides common scenarios' solutions for ASP.NET Core applications.
C#
130
star
13

PdfReport

PdfReport is a code first reporting engine, which is built on top of the iTextSharp and EPPlus libraries.
C#
91
star
14

EnglishToPersianDictionaries

A collection of English to Persian dictionaries
Java
87
star
15

EFSecondLevelCache

Entity Framework 6.x Second Level Caching Library.
C#
65
star
16

DNTProfiler

DNTProfiler is an EF 6.x and NH 4.x profiler.
C#
59
star
17

PersianBingCalendar

Bing daily wallpaper images with Persian calendar
C#
58
star
18

DNTScanner.Core

DNTScanner.Core is a .NET 4x and .NET Core 2x+ wrapper for the Windows Image Acquisition library.
C#
57
star
19

IdentityServerImageGallery

How to use IdentityServer 4.x with an ASP.NET Core app
C#
55
star
20

JwtWithWebAPI

Creating a RESTful API with authentication using Web API 2.x and JSON Web Tokens
JavaScript
44
star
21

DNTScheduler.Core

DNTScheduler.Core is a lightweight ASP.NET Core's background tasks runner and scheduler
C#
44
star
22

DNTPersianComponents.Blazor

A collection of Persian components for Blazor
SCSS
39
star
23

DNTBreadCrumb.Core

DNTBreadCrumb.Core Creates custom bread crumb definitions, based on Twitter Bootstrap features for ASP.NET Core applications.
SCSS
32
star
24

AspNetIdentityDependencyInjectionSample

ASP.NET Identity Dependency Injection Sample
JavaScript
31
star
25

ASPNETCore2CookieAuthentication

Cookie Authentication without ASP.NET Core Identity 7x
SCSS
31
star
26

angular-template-driven-forms-lab

A collection of tips and tricks about how to use an Angular (2+) app with an ASP.NET Core app.
TypeScript
30
star
27

DNTCaptcha.Blazor

A captcha generator for the Blazor based applications.
SCSS
30
star
28

AutoMapperSamples

Using AutoMapper with Entity Framework.
C#
26
star
29

QueryingInEFCore

Querying in Entity Framework Core
C#
25
star
30

IranianITBloggers

A collection of RSS feeds of Iranian IT bloggers
25
star
31

DNTScheduler

DNTScheduler is a super simple ASP.NET's background tasks runner and scheduler.
C#
24
star
32

MvcPlugin

How to create plugins for ASP.NET MVC 4.x/5.x applications.
C#
22
star
33

SubtitleTools

SubtitleTools is a small utility that helps modifying existing subtitles or downloading new ones
C#
21
star
34

AngularMaterialLab

A collection of tips and tricks about how to use an Angular Material 9x app with an ASP.NET Core app
TypeScript
21
star
35

HotelManagementSample

This is a sample project to demonstrate how to work with EF-Core, Web-API, ASP.NET Core identity, Blazor Wasm and Blazor Server
C#
20
star
36

BlazorWasmDynamicPermissions

Blazor WASM Dynamic Permissions
SCSS
19
star
37

KendoUI-Samples

Using KendoUI with ASP.NET.
JavaScript
16
star
38

Exports

Expotred files of the .NET Tips.
C#
15
star
39

WpfFramework

Using Entity framework code-first and unit of work pattern with WPF applications.
C#
14
star
40

DntConsole

This a .NET 7x console app template
C#
14
star
41

KendoUI.Core.Samples

Using KendoUI with ASP.NET Core
JavaScript
14
star
42

SignalR-Samples

Using SiganlR in ASP.NET applications.
JavaScript
13
star
43

Froala-Sample

Using Froala WYSIWYG Editor with ASP.NET
JavaScript
12
star
44

Dependency-Injection-Samples

.NET Dependency Injection Samples
C#
12
star
45

ElmahEFLogger

Global exceptions logger for Entity Framework 6.x using ELMAH
C#
12
star
46

Solution-Template-Generator

Solution template generator, gets a .SLN file containing multiple projects and then converts it to a .VSIX file
C#
12
star
47

jqGrid-Samples

Using jqGrid with ASP.NET MVC
JavaScript
11
star
48

DNTBreadCrumb

DNTBreadCrumb Creates custom bread crumb definitions, based on Twitter Bootstrap 3.x features
C#
11
star
49

MVC5Angular2

Using AngularJS 2.0 with ASP.NET MVC 5.x
TypeScript
11
star
50

ApiUrlsGenerator

This library will help you to convert your `stringly typed` API URL's to strongly typed ones
C#
8
star
51

Mvc-App-Persian-DatePicker

Using JavaScript PersianDatePicker in ASP.NET applications.
CSS
7
star
52

UoW-Sample

Using multiple databases with EF Code First, UoW & DI patterns.
C#
7
star
53

EFCoreSQLiteFTS

Implementing full-text search with SQLite and EF-Core
C#
7
star
54

AOP-Sample

AOP Samples, mostly using StructureMap & Castle.Core
C#
4
star
55

Silverlight-Persian-DatePicker

Silverlight 4 & 5 Persian DatePicker
C#
3
star
56

DntSite

این پروژه، سورس کامل و در حال استفاده‌ی وب‌سایت «دات‌نت تيپس» است
C#
3
star
57

MVC-Samples

ASP.NET MVC Step By Step
C#
3
star
58

MVC-Ajax-Form-Upload

Adding file upload support to Ajax.BeginForm
JavaScript
3
star
59

ExplorerPCal

Replacing the default Windows calendar with .NET hooks
C#
3
star
60

ProxyValidator

An automated service for validating free to use proxy servers
C#
2
star
61

RemovePdfLinks

Pdf Links Remover.
C#
1
star
62

Disposable-Email-Address-Detector

Using nameapi.org's API in .NET
C#
1
star
63

OpenAPISwaggerDoc

This is a sample project to show how to use the OpenAPI Swagger in .NET apps
C#
1
star
64

.NET-Persian-Subtitles

Persian subtitles for the various .NET related courses
HTML
1
star
65

OxyPlotWpfTests

An OxyPlot Sample
C#
1
star