C# 的 Entity Framework (EF) 和 Java 的 Spring 框架都是用于构建企业级应用程序的流行框架。它们提供了许多相似的功能,如数据持久化、依赖注入、事务管理等,但在语法和生态系统方面有所不同。
在 Entity Framework (EF) 中,LINQ 语句可以用于对数据库进行增删改查操作。以下是一些示例:
查询 (Retrieve)
using (var context = new YourDbContext())
{
var result = context.YourEntities.Where(e => e.SomeProperty == someValue).ToList();//或者ToListAsync()
}
YourDbContext())
{
var entities = context.Entities.AsNoTracking().ToList();
使用AsNoTracking可以提高性能,因为它避免了跟踪实体状态的开销。
多条件查询
using (var context = new YourDbContext())
{
var result = context.YourEntities.Where(m => !m.IsRemove && m.Name.Contains(obj.Name).ToListAsync();
}
模糊查询(Contains)
context .YourEntities.Where(m => m.IsRemove != true && m.UnitNumber.Contains(obj.UnitNumber)).ToListAsync();
分组查询
context.YourDbContext.AsNoTracking().GroupBy(x => new { x.Type, x.Region }).Select(x => new YourDbContext
{
Type = x.Key.Type,
Region = x.Key.Region,
}).ToListAsync();
查询字段的最大值
var Num = (await context.YourDbContext.AsNoTracking().Select(x => !string.IsNullOrEmpty(x.Num) ? int.Parse(x.Num) : 0).ToListAsync()).Max();
查询一条数据 Id字段
//FirstOrDefaultAsync()方法会返回序列中的第一个元素,如果没有找到元素,则返回默认值(对于int类型,这将是0)
int Id = await context.YourDbContext
.Where(m => !m.IsRemove)
.Select(m => m.Id)
.FirstOrDefaultAsync();
Dto查询
try
{
var data = await context.YourDbContext
.Where(m => !m.IsRemove && m.WcName.Contains(obj))
.Select(m => new YouDto
{
Id = m.Id,
Name = m.Name
})
.ToListAsync();
var count = await context.YourDbContext.CountAsync();
return new Tips<List<YouDto>>() { Code = Msg.Yes, Count = count, Data = data };
}
catch (Exception e)
{
return new Tips<List<YouDto>>() { Code = Msg.Err, Message = e.Message };
}
两表连查
// 从表 table1 中查询未被移除且 TypeId 等于 type[0] 的数据
var data = await context.table1
.Where(m => !m.IsRemove && m.TypeId == obj.id)
.Join(
// 将 table1 和 table2 进行连接,连接条件为 table1 的 TypeId 等于 table2 的 Id
context.table2,
m => m.TypeId, // table1 的连接字段
YouType => YouType.Id, // table2 的连接字段
// 将连接结果投影为 youDot 对象
(m, YouType) => new youDot
{
Id = m.Id,
Small = m.Small,
TypeId = m.TypeId,
TypeName = YouType.TypeName,
}
)
.ToListAsync();
三表连查
.Where(m => !m.IsRemove && m.TypeId == obj.id)
.Join(
// 首先连接 table1 和 table2
context.table2,
m => m.TypeId, // table1 的连接字段
YouType => YouType.Id, // table2 的连接字段
(m, YouType) => new { m, YouType } // 临时投影成匿名对象
)
.Join(
// 现在连接 table2 和 table3
context.table3,
combined => combined.m.SomeForeignKey, // 使用来自 table1 的连接字段
table3 => table3.Id, // table3 的连接字段
(combined, table3) => new youDot // 将最终结果投影为 youDot 对象
{
//与上面两表一样
}
)
.ToListAsync(); // 将结果异步转换为列表
或者
List<YouDto> data = await
(from a in context.Table1.AsNoTracking()
join b in context.Table2.AsNoTracking() on a.bId equals b.Id
join c in context.Table3.AsNoTracking() on a.mId equals m.Id
select new YouDto {
}).ToListAsync();
包含查询
data = await context. YourDbContext.Where(m => !m.IsRemove && obj.Contains(m.Type)).ToListAsync();
分页查询
data = await context.YourDbContext.OrderByDescending(m => m.CreateTime).Skip(页数) * 条数).Take(查询条数).Where(m => !m.IsRemove).ToListAsync();
条件+连表查询
/// <summary>
/// 查询记录信息表
/// </summary>
/// <param name="search">查询条件字符串</param>
/// <param name="type">查询类型 (-1: 全查, 1: 根据ID查询, 2: 根据日期查询)</param>
/// <returns>包含查询结果的响应对象</returns>
public async Task<Response<List<RecordDto>>> GetData(string search, int type)
{
try
{
// 定义查询条件表达式
Expression<Func<Record, bool>> predicate;
switch (type)
{
case -1:
// 全查:只查询未删除的记录
predicate = r => !r.IsDeleted;
break;
case 1:
// 根据ID查询:转换查询条件为整数ID
predicate = r => r.Id == int.Parse(search);
break;
case 2:
// 根据日期查询:解析日期范围
DateTime startDate = DateTime.Parse(search);
DateTime endDate = DateTime.Parse(search);
predicate = r => r.RecordDate >= startDate && r.RecordDate <= endDate;
break;
default:
// 默认查询:只查询未删除的记录
predicate = r => !r.IsDeleted;
break;
}
// 从不同表中获取未删除的数据
var data1 = context.Records.Where(predicate).AsNoTracking();
var data2 = context.Locations.Where(l => !l.IsDeleted).AsNoTracking();
var data3 = context.Info.Where(i => !i.IsDeleted).AsNoTracking();
var data4 = context.Users.Where(u => !u.IsDeleted).AsNoTracking();
// 联合查询,生成结果列表
var data = await (from r in data1
join l in data2 on r.LocationId equals l.Id into r_l
from r_l_ in r_l.DefaultIfEmpty()
join i in data3 on r.InfoId equals i.Id into r_i
from r_i_ in r_i.DefaultIfEmpty()
join u in data4 on r.UserId equals u.Id into r_u
from r_u_ in r_u.DefaultIfEmpty()
select new RecordDto
{
RecordNumber = r.RecordNumber,
RecordDate = r.RecordDate,
EntryDate = r.EntryDate,
LocationId = r.LocationId,
LocationName = r_l_ == null ? "" : r_l_.Name, // 如果没有匹配到,使用空字符串
InfoId = r.InfoId,
InfoName = r_i_ == null ? "" : r_i_.InfoName + "/" + r_i_.AdditionalInfo, // 拼接信息名称和附加信息
UserId = r.UserId,
UserName = r_u_.UserName, // 使用用户名称
Notes = r.Notes,
ApprovalStatus = r.ApprovalStatus,
ApprovalTime = r.ApprovalTime,
ApprovalUser = r.ApprovalUser,
ModifiedBy = r.ModifiedBy,
ModifiedTime = r.ModifiedTime,
}).ToListAsync();
// 返回成功的响应结果
return new Response<List<RecordDto>> { Code = StatusCode.Success, Data = data };
}
catch (Exception e)
{
// 捕获异常并返回错误的响应结果
return new Response<List<RecordDto>> { Code = StatusCode.Error, Message = e.ToString() };
}
}
一个简单的树形结构
var data = await context.YourDbContext.Where(m => !m.IsRemove).ToListAsync();
var types = data.Select(m => m.UnitType).Distinct().ToList();
List<TreeDto> list = new List<TreeDto>();
TreeDto groupTypeDto = new TreeDto();
groupTypeDto.id = 0;
groupTypeDto.label = "类别";
foreach (var type in types)
{
groupTypeDto.children.Add(new TreeDto
{
id = 1,
label = type
});
}
list.Add(groupTypeDto);
return new Tips<List<TreeDto>>() { Code = Msg.Yes, Data = list };
根据一个字段的值查询树结构(多级分类树)
• 根节点:所有数据的起点,通常是一个虚拟节点(在你的代码中是“全部数据”)。
• 父节点:位于根节点之下的节点,包含一个点(.)。
• 子节点:位于父节点之下的节点,包含两个点(.)。
Id | TypeNumber |
---|---|
1 | 100 |
2 | 100.1 |
3 | 100.2 |
4 | 100.1.1 |
5 | 100.1.2 |
6 | 200 |
7 | 200.1 |
树结构如下:
• 全部数据
• 100
• 100.1
• 100.1.1
• 100.1.2
• 100.2
• 200
• 200.1
public async Task<Tips<List<TreeDto>>> GetTree()
{
try
{
// 从数据库中查询未被删除的所有记录
var data = await context.表名.Where(m => !m.IsRemove).ToListAsync();
// 初始化树形数据结构列表
List<TreeDto> treeDtosList = new List<TreeDto>();
// 创建一个特殊的根节点 "全部数据"
TreeDto rootTreeDto = new TreeDto
{
label = "全部数据",
children = new List<TreeDto>()
};
// 遍历数据库中查询到的数据
for (int i = 0; i < data.Count; i++)
{
// 获取类型编号中的第一个和最后一个点的位置
int firstDotIndex = data[i].TypeNumber.IndexOf('.');
int secondDotIndex = data[i].TypeNumber.LastIndexOf('.');
// 检查类型编号中包含点的数量
bool hasOneDot = firstDotIndex != -1 && secondDotIndex == firstDotIndex;
bool hasTwoDots = firstDotIndex != -1 && secondDotIndex != -1 && secondDotIndex != firstDotIndex;
if (hasOneDot)
{
// 父节点处理
TreeDto parentTreeDto = new TreeDto
{
id = data[i].Id,
label = data[i].TypeNumber,
children = new List<TreeDto>()
};
// 将父节点添加到根节点的子节点列表中
rootTreeDto.children.Add(parentTreeDto);
}
else if (hasTwoDots)
{
// 子节点处理
string parentTypeNumber = data[i].TypeNumber.Substring(0, secondDotIndex);
// 在根节点的子节点中找到对应的父节点
var parentTreeDto = rootTreeDto.children.FirstOrDefault(t => t.label == parentTypeNumber);
if (parentTreeDto != null)
{
TreeDto childTreeDto = new TreeDto
{
id = data[i].Id,
label = data[i].TypeNumber
};
// 将子节点添加到对应的父节点中
parentTreeDto.children.Add(childTreeDto);
}
}
else
{
// 根节点处理
TreeDto rootChildTreeDto = new TreeDto
{
id = data[i].Id,
label = data[i].TypeNumber,
children = new List<TreeDto>()
};
// 将根节点直接添加到根节点的子节点列表中
rootTreeDto.children.Add(rootChildTreeDto);
}
}
// 将根节点添加到树形数据结构列表中
treeDtosList.Add(rootTreeDto);
// 返回构建好的树形数据结构
return new Tips<List<TreeDto>>() { Code = Msg.Yes, Data = treeDtosList };
}
catch (Exception e)
{
// 捕获异常并返回错误信息
return new Tips<List<TreeDto>>() { Code = Msg.Err, Message = "查询失败!" };
}
}
递归方式(多级分类树)
public async Task<Tips<List<YourTreeDto>>> GetTree()
{
try
{
List<YourTreeDto> Tree = new List<YourTreeDto>();
Tree.Add(new YourTreeDto
{
id = 0,
parentId = -1,
label = "类型"
});
List<Type> data = await context.YourTable.Where(m => !m.IsRemove).ToListAsync();
MateriaType(Tree, data, 0);
return new Tips<List<YourTreeDto>> { Code = Msg.Yes, Data = Tree };
}
catch (Exception e)
{
return new Tips<List<YourTreeDto>> { Code = Msg.Err, Message = "错误", };
}
}
public void Type(List<YourTreeDto> Tree, List<Type> data, int ParentId)
{
var T = data.Where(m => m.ParentId == ParentId).ToList();
foreach (var child in T)
{
var node = new YourTreeDto
{
id = child.Id,
label = child.TypeName ,
parentId = child.ParentId,
children = new List<YourTreeDto>()
};
Type(node.children, data, child.Id);
Tree.Add(node);
}
}
添加 (Create)
using (var context = new YourDbContext())
{
var newEntity = new YourEntity { SomeProperty = someValue };
context.YourEntities.Add(newEntity);
context.SaveChanges();
}
修改 (Update)
using (var context = new YourDbContext())
{
var entityToUpdate = context.YourEntities.FirstOrDefault(e => e.Id == entityId);
if (entityToUpdate != null)
{
entityToUpdate.SomeProperty = newValue;
context.SaveChanges();
}
}
批量保存
//Any是一个LINQ方法,用于检查warehouse列表中是否有任何对象的Id与数据库中的Id相匹配。
var list = await context.YourDbContext.Where(t => warehouse.Any(x=>x.Id==t.Id)).ToListAsync();
context.YourDbContext.UpdateRange(list);
await context.SaveChangesAsync();
return new Tip() { Code = Msg.Yes, Message = "操作成功!" };
删除 (Delete)
using (var context = new YourDbContext())
{
var entityToDelete = context.YourEntities.FirstOrDefault(e => e.Id == entityId);
if (entityToDelete != null)
{
context.YourEntities.Remove(entityToDelete);
context.SaveChanges();
}
}
批量删除
var list = await context.YourDbContext.Where(t => ids.Contains(t.Id)).ToListAsync();
context.YourDbContext.RemoveRange(list);
await context.SaveChangesAsync();
return new Tip() { Code = Msg.Yes, Message = "删除成功" };
事务回滚
//嵌套try外层
using (var tran = context.Database.BeginTransaction())
{
try
{
tran.Commit();
//如果事务中的所有数据库操作都成功,那么这个事务就会被提交
catch (Exception e)
{
tran.Rollback();
//在事务中进行的所有更改都会被撤销
return new Tip() { Code = Msg.Err, Message = "失败!" };
}
}
字符串的左侧填充0
str.ToString().PadLeft(4, '0')