# efcore

#### dotnet -ef 乱码修复

```bash
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
```

#### 防止并发修改

```c#
1 乐观锁（推荐）
在实体中添加版本号或时间戳字段，每次更新时检查版本是否变化
public class Entity
{
public int Id { get; set; }
public string Name { get; set; }
public int Version { get; set; } // 版本号
}
// EF Core 配置
modelBuilder.Entity<Entity>().Property(e => e.Version).IsConcurrencyToken();
// 更新时自动检查
var entity = await context.Entities.FindAsync(id);
entity.Name = "new name";
await context.SaveChangesAsync(); // 如果版本冲突会抛出 DbUpdateConcurrencyException
捕获异常后处理：
try
{
await context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
// 重新加载最新数据，合并变更或提示用户
}
2 悲观锁
使用数据库行锁，适合高冲突场景
// SQL Server
SELECT * FROM Entities WITH (UPDLOCK, ROWLOCK) WHERE Id = @id
// MySQL
SELECT * FROM Entities WHERE Id = @id FOR UPDATE
在 EF Core 中执行原始 SQL 锁定，然后在事务中更新
3 分布式锁
适合跨服务或多实例场景，使用 Redis 等
var lockKey = $"lock:entity:{id}";
var acquired = await redis.StringSetAsync(lockKey, "1", TimeSpan.FromSeconds(10), When.NotExists);
if (!acquired)
{
throw new Exception("资源正在被其他请求修改");
}
try
{
// 执行更新操作
}
finally
{
await redis.KeyDeleteAsync(lockKey);
}
4 业务层面控制
接口幂等性设计，前端防重复提交，后端验证状态
建议优先使用乐观锁，性能最好且实现简单。高冲突场景再考虑悲观锁或分布式锁。
```