ASP.NET+Entity Framework无法写入数据库的问题排查
我是编程学徒,做一个小型ASP.NET项目,用Entity Framework(DB-first模式)保存文件上传记录到数据库时触发System.NullReferenceException。场景是用户上传文件到项目文件夹,同时把文件名称、路径、上传时间、上传人等数据写入数据库。
相关代码
前端上传控件代码
<asp:FileUpload ID="fileUpload" AllowMultiple="true" runat="server" class="mb-3" />
后台点击事件处理代码
protected void sBtnUpload_Click(object sender, EventArgs e) { if (fileUpload.HasFiles) { using (WS_TestEntities1 dbContext = new WS_TestEntities1()) { if (dbContext != null) { foreach (HttpPostedFile uploadedFile in fileUpload.PostedFiles) { string fileName = Path.GetFileName(uploadedFile.FileName); string filePath = Server.MapPath("~/Uploads/") + fileName; uploadedFile.SaveAs(filePath); fileUpload.Attributes.Clear(); Statuten newStatut = new Statuten { sName = "name", sDatenpfad = "path", sUploadDateTime = DateTime.Now, sUploadId = "Hans Maier" }; dbContext.Statutens.Add(newStatut); dbContext.SaveChanges(); } } } } }
错误信息
System.NullReferenceException: Object reference not set to an instance of an object.
错误触发在dbContext.SaveChanges()调用,但调用dbContext.Statutens.Add(newStatut)时就已出现异常,Add方法的Buffer、Cache等属性触发System.Web.HttpException,id值为0。尝试过重新加载数据库对象、修改现有数据,均无效。
更新信息
更新1:实体与DbContext定义
采用DB-first模式,Model.Context.cs中定义:
public virtual DbSet<Statuten> Statutens { get; set; }
实体类Statuten(对应英文Documents)定义:
public partial class Statuten { public int id { get; set; } public string sName { get; set; } public string sDatenpfad { get; set; } public Nullable<System.DateTime> sUploadDateTime { get; set; } public string sUploadId { get; set; } }
DbContext定义:
public partial class WS_TestEntities1 : DbContext { public WS_TestEntities1() : base("name=WS_TestEntities1") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public virtual DbSet<...> Persons { get; set; } public virtual DbSet<...> Apts { get; set; } public virtual DbSet<...> Loans { get; set; } public virtual DbSet<...> Firms{ get; set; } public virtual DbSet<Statuten> Statutens { get; set; } }
更新2:详细错误栈追踪
Object reference not set to an instance of an object.
Description: 执行当前Web请求期间发生未处理异常,请查看栈追踪获取错误详情及代码起源。
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
源代码错误位置:
Line 93: Line 94: } Line 95: dbContext.SaveChanges(); Line 96: } Line 97: }
文件路径:C:\Users...\Statuten.aspx.cs 第95行
栈追踪:
[NullReferenceException: Object reference not set to an instance of an object.] System.Web.UI.ParseChildrenAttribute.GetHashCode() +32 System.Collections.Generic.ObjectEqualityComparer`1.GetHashCode(T obj) +22 System.Linq.Set`1.InternalGetHashCode(TElement value) +74 System.Linq.Set`1.Find(TElement value, Boolean add) +40 System.Linq.<ExceptIterator>d__73`1.MoveNext() +291 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +452 System.Linq.Enumerable.ToList(IEnumerable`1 source) +68 System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) +74 System.Data.Entity.Internal.Validation.EntityValidatorBuilder.BuildPropertyValidator(PropertyInfo clrProperty) +29 System.Data.Entity.Internal.Validation.EntityValidatorBuilder.BuildValidatorsForProperties(IEnumerable`1 clrProperties, IEnumerable`1 edmProperties, IEnumerable`1 navigationProperties) +1197 System.Data.Entity.Internal.Validation.EntityValidatorBuilder.BuildTypeValidator(Type clrType, IEnumerable`1 edmProperties, IEnumerable`1 navigationProperties, Func`3 validatorFactoryFunc) +56 System.Data.Entity.Internal.Validation.EntityValidatorBuilder.BuildEntityValidator(InternalEntityEntry entityEntry) +240 System.Data.Entity.Internal.Validation.ValidationProvider.GetEntityValidator(InternalEntityEntry entityEntry) +95 System.Data.Entity.Internal.InternalEntityEntry.GetValidationResult(IDictionary`2 items) +67 System.Data.Entity.DbContext.GetValidationErrors() +329 System.Data.Entity.Internal.InternalContext.SaveChanges() +44 WS_Test_Elemente.Statuten.sBtnUpload_Click(Object sender, EventArgs e) in C:\Users\kaspar.schultess\source\repos\WS_Test_Elemente\WS_Test_Elemente\Statuten.aspx.cs:95 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +137 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +149 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5439
排查与解决步骤
移除
fileUpload.Attributes.Clear()调用
循环内调用fileUpload.Attributes.Clear()会清空上传控件的所有属性,导致后续EF验证时访问控件相关属性出现空引用。直接删除这行代码,或移到所有数据库操作完成后执行。检查EF实体主键配置
从栈追踪看错误发生在EF构建实体验证器阶段,确认数据库中id字段是自增主键,DB-first生成的实体是否正确标记了主键特性。如果没有,手动在id属性上添加[System.ComponentModel.DataAnnotations.Key]特性。调整
SaveChanges调用时机
当前每次循环都调用SaveChanges(),改为循环结束后统一调用,减少数据库交互次数,避免多次触发验证的问题:foreach (HttpPostedFile uploadedFile in fileUpload.PostedFiles) { string fileName = Path.GetFileName(uploadedFile.FileName); string filePath = Server.MapPath("~/Uploads/") + fileName; uploadedFile.SaveAs(filePath); Statuten newStatut = new Statuten { sName = fileName, sDatenpfad = filePath, sUploadDateTime = DateTime.Now, sUploadId = "Hans Maier" }; dbContext.Statutens.Add(newStatut); } dbContext.SaveChanges();重新生成EDMX模型
尝试从数据库重新更新EDMX模型,确保实体类与数据库结构完全一致,避免因模型与数据库不匹配导致的验证错误。
内容的提问来源于stack exchange,提问作者Kaspar

