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

浙公网安备 33010602011771号