使用ADO.NET连接SharePoint列表引发内存泄漏问题
一、控制台程序挂起问题修复
你的代码执行后程序挂起、内存占用无法释放,核心原因是非托管资源未彻底回收——ACE OLEDB驱动即使调用Close/Dispose,仍可能残留后台线程。修复方案如下:
- 所有实现
IDisposable的对象必须用using包裹(你的代码中oledbAdapter未纳入using范围) - 程序退出前强制触发垃圾回收(仅控制台场景临时使用,业务代码不推荐)
- 移除冗余的手动
Close/Dispose调用(using会自动处理)
修改后的ADONetImplementationWithAdapter方法:
static void ADONetImplementationWithAdapter() { using (OleDbConnection conn = new OleDbConnection(ConnectionStringBase)) using (OleDbDataAdapter oledbAdapter = new OleDbDataAdapter(sql, conn)) { DataSet ds = new DataSet(); conn.Open(); oledbAdapter.Fill(ds); for (int i = 0; i < ds.Tables[0].Rows.Count; i++) { Console.WriteLine($"{ds.Tables[0].Rows[i].ItemArray[0]} -- {ds.Tables[0].Rows[i].ItemArray[1]}"); } } }
在Main方法末尾添加资源回收代码:
// 强制回收非托管资源 GC.Collect(); GC.WaitForPendingFinalizers();
二、不依赖传统SharePoint API的现代连接方案
ACE OLEDB属于老旧技术,推荐以下三种现代化替代方案:
方案1:SharePoint REST API(原生HTTP调用,无额外依赖)
直接通过HTTP请求访问列表数据,适配所有.NET版本:
using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; static async Task GetListDataViaRest() { var siteUrl = "https://.../sites/..."; var listName = "Call Distributions"; var apiUrl = $"{siteUrl}/_api/web/lists/getbytitle('{listName}')/items?$top=10"; using (var client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json;odata=nometadata")); // 域环境启用默认凭据,云环境需替换为OAuth认证 client.UseDefaultCredentials = true; var response = await client.GetAsync(apiUrl); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); var items = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(json); foreach (var item in items) { Console.WriteLine($"{item["ID"]} -- {item["Title"]}"); } } }
方案2:PnP Core SDK(微软官方推荐的现代化库)
轻量级、跨平台的SharePoint开发库,支持.NET Core/.NET 5+:
- 安装NuGet包:
PnP.Core、PnP.Core.Auth - 代码示例:
using PnP.Core.Services; static async Task GetListDataViaPnP() { var siteUrl = "https://.../sites/..."; // 交互式认证,支持ClientSecret、证书等多种认证方式 var authProvider = new InteractiveAuthenticationProvider(siteUrl); using (var context = await PnPContextFactory.CreateAsync(siteUrl, authProvider)) { var list = await context.Web.Lists.GetByTitleAsync("Call Distributions"); var items = await list.Items.Take(10).GetAsync(); foreach (var item in items) { Console.WriteLine($"{item.Id} -- {item.Title}"); } } }
方案3:Entity Framework Core(第三方库支持)
通过第三方库实现EF Core对接SharePoint,实现ORM化操作:
- 安装NuGet包:
SharePoint.EntityFrameworkCore - 定义实体类:
public class CallDistribution { public int Id { get; set; } public string Title { get; set; } // 对应列表其他字段 }
- DbContext配置与查询:
using Microsoft.EntityFrameworkCore; public class SharePointDbContext : DbContext { public DbSet<CallDistribution> CallDistributions { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSharePoint("https://.../sites/...", "Call Distributions"); } } // 查询示例 using (var db = new SharePointDbContext()) { var items = db.CallDistributions.Take(10).ToList(); foreach (var item in items) { Console.WriteLine($"{item.Id} -- {item.Title}"); } }
内容的提问来源于stack exchange,提问作者chrisdyck
相关产品推荐
相关产品推荐

