.net 一些常用高级使用方法

一、Entity Framework Core 中乐观锁和悲观锁

乐关锁:用户读取数据时不锁定数据。当一个用户 SaveChanges 时,系统将进行检查,查看该用户读取数据后其他用户是否又更改了该数据。如果其他用户更新了数据,将产生一个错误。

/// <summary>
/// ef code 乐观并发
/// </summary>
[ConcurrencyCheck]
public Guid Version { get; set; }

/// <summary>
/// ef code 乐观并发
/// </summary>
[Timestamp]
public byte[] RowVersion { get; set; }

//也可以在实体约束上应用乐观并发(针对某行数据)
modelBuilder.Entity<Person>().Property(p => p.RowVersion).IsRowVersion();

//或 使用并发令牌 (针对某个属性)
builder.Property(h => h.Name).IsConcurrencyToken();

 悲观锁:LOCK、Monitor、Interlocked 等锁定数据的方式,属于悲观并发处理范畴,需要根据不同数据库,自行实现EF 暂时没有该;(该用户读取数据后就锁定数据,当其它用户读取时会产生一个错误)

二、常用的缓存

ConcurrentDictionary<TKey, TValue> 用于多线程环境下的键值对集合的类,它提供了线程安全的操作,如添加、删除和访问元素。

//范例
public class DictionaryCache
{
    private readonly ConcurrentDictionary<string, AuthKeys> cache = [];
    public AuthKeys GetOrAdd(string key, AuthKeys value) {
        return this.cache.GetOrAdd(key, value);
    }
    public AuthKeys AddOrUpdate(string key, AuthKeys value)    {
        return this.cache.AddOrUpdate(key, value, (k, v) => value);
    }
    public bool TryGetValue(string key, out AuthKeys? value)    {
        return this.cache.TryGetValue(key, out value);
    }
    public bool Remove(string key)    {
        return this.cache.TryRemove(key, out _);
    }
}

  

MemoryStream 内存缓存服务

//需要先注册服务 services.AddMemoryCache();

/// <summary> /// 缓存服务 /// </summary> public class CacheService { private readonly IMemoryCache memoryCache; public CacheService(IMemoryCache memoryCache) { this.memoryCache = memoryCache; } /// <summary> /// 设置缓存 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="options"></param> public void Set<T>(string key, T value, MemoryCacheEntryOptions? options = null) { if (options == null) { options = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60), }; options.RegisterPostEvictionCallback(MemoryCacheDelegate); } this.memoryCache.Set(key, value, options); } /// <summary> /// 获取 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T? Get<T>(string key) { return this.memoryCache.TryGetValue(key, out T? value) ? value : default; } /// <summary> /// 当删除或过期时执行的回调方法 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="reason"></param> /// <param name="state"></param> private void MemoryCacheDelegate(object key, object? value, EvictionReason reason, object? state) { if (reason == EvictionReason.Removed || reason == EvictionReason.Expired) { //当过期或被移除时执行的操作 } } }

 

IDistributedCache 分布式缓存

// 分布式内存缓存,Microsoft.Extensions.Caching.Memory
services.AddDistributedMemoryCache((s) =>
{
    s.TrackLinkedCacheEntries = true; // 启用分布式缓存的链接跟踪功能
    s.CompactionPercentage = 0.2; // 设置分布式缓存的压缩百分比
    s.ExpirationScanFrequency = TimeSpan.FromMinutes(5); // 设置分布式缓存的过期扫描频率
    s.SizeLimit = 1024 * 1024 * 100; // 设置分布式缓存的大小限制为100MB
    s.TrackStatistics = true; // 启用分布式缓存的统计信息跟踪功能
});

// Redis 分布式缓存,Microsoft.Extensions.Caching.StackExchangeRedis
services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration.GetConnectionString("MyRedisConStr");
    options.InstanceName = "SampleInstance";
});

 

public class CaptchaCacheService(IDistributedCache cache)
{
    private const string key = "send_captcha_{0}";
    private readonly IDistributedCache cache = cache;

    /// <summary>
    /// 缓存
    /// </summary>
    /// <param name="key"></param>
    /// <param name="captcha"></param>
    /// <param name="timeout">超时(默认5分钟)</param>
    /// <returns></returns>
    public Task SetAsync(string key, string captcha, int timeout = 5)
    {
        DistributedCacheEntryOptions options = new()
        {
            SlidingExpiration = TimeSpan.FromMinutes(timeout),
        };
        return cache.SetStringAsync(string.Format(key, key), captcha, options);
    }
}

  

RecyclableMemoryStream 提供高性能的内存流管理,通过池化技术优化了 MemoryStream 对象的使用,从而显著提升了应用程序的性能,特别是在垃圾回收(GC)方面;主要用于大对象的内存流的管理;

Install-Package Microsoft.IO.RecyclableMemoryStream

class Program
{
    private static readonly RecyclableMemoryStreamManager manager = new RecyclableMemoryStreamManager();

    static void Main(string[] args)
    {
        var sourceBuffer = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
        
        using (var stream = manager.GetStream())
        {
            stream.Write(sourceBuffer, 0, sourceBuffer.Length);
        }
    }
}

  

三、内存队列 

Channel 具有异步API,高性能,线程安全等特点,它可以用来做消息队列,进行数据的生产和消费;

可以配置队列超过最大容量后数据片是规则:

  • Wait 是默认值,当 channel 容量满了以后,写入数据时会返回 false,直到channel有数据被消费了以后,才可以继续写入
  • DropNewest 移除最新的数据,也就是从队列尾部开始移除
  • DropOldest 移除最老的数据,也就是从队列头部开始移除
  • DropWrite 写入数据返回成功,但是转头就把刚才的数据丢了
/// <summary>
/// 内存队列服务
/// </summary>
public class ChannelService
{
    private readonly Channel<string> channels;

    public ChannelService()
    {
        var maxCapacity = 1000; //有界通道可以存储的最大容量。
        this.channels = Channel.CreateBounded<string>(new BoundedChannelOptions(maxCapacity)
        {
            //如果通道已满,则丢弃最新的项。
            FullMode = BoundedChannelFullMode.DropNewest
        });
    }

    /// <summary>
    /// 并行队列消费
    /// </summary>
    /// <returns></returns>
    public Task ConsumeAsync(Func<string, CancellationToken, ValueTask> callBack, CancellationToken cancellationToken)
    {
        var sources = channels.Reader.ReadAllAsync(cancellationToken);
        var maxDegree = 4; // 最大并行度,默认为4
        var parallelOptions = new ParallelOptions
        {
            CancellationToken = cancellationToken,
            MaxDegreeOfParallelism = maxDegree
        };
        return Parallel.ForEachAsync(sources, parallelOptions, callBack);
    }

    /// <summary>
    /// 并行队列消费
    /// </summary>
    /// <returns></returns>
    public Task ConsumeAsync(CancellationToken cancellationToken)
    {
        return ConsumeAsync(ConsumeAsync, cancellationToken);
    }

    /// <summary>
    /// 处理数据的逻辑
    /// </summary>
    /// <param name="item"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async ValueTask ConsumeAsync(string data, CancellationToken cancellationToken)
    {
        await Task.Delay(1000, cancellationToken); // 模拟处理延迟
        Console.WriteLine($"Processed item: {data}");
    }

    /// <summary>
    /// 生产数据
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public bool Write(string data)
    {
        return channels.Writer.TryWrite(data);
    }
}

  

posted @ 2025-07-17 14:12  皓月青峰  阅读(11)  评论(0)    收藏  举报