在Linq中调用InsertOnSubmit到Sql时出现NullReferenceException

我正在尝试使用LINQ to SQL将新对象插入到我的数据库中,但是当我在下面的代码片段中调用InsertOnSubmit()时,会获得NullReferenceException。 我传入一个名为FileUploadAudit的派生类,并设置了该对象的所有属性。

public void Save(Audit audit) { try { using (ULNDataClassesDataContext dataContext = this.Connection.GetContext()) { if (audit.AuditID > 0) { throw new RepositoryException(RepositoryExceptionCode.EntityAlreadyExists, string.Format("An audit entry with ID {0} already exists and cannot be updated.", audit.AuditID)); } dataContext.Audits.InsertOnSubmit(audit); dataContext.SubmitChanges(); } } catch (Exception ex) { if (ObjectFactory.GetInstance().HandleException(ex)) { throw; } } } 

这是堆栈跟踪:

 at System.Data.Linq.Table`1.InsertOnSubmit(TEntity entity) at XXXX.XXXX.Repository.AuditRepository.Save(Audit audit) C:\XXXX\AuditRepository.cs:line 25" 

我已经像这样添加到Audit类:

 public partial class Audit { public Audit(string message, ULNComponent component) : this() { this.Message = message; this.DateTimeRecorded = DateTime.Now; this.SetComponent(component); this.ServerName = Environment.MachineName; } public bool IsError { get; set; } public void SetComponent(ULNComponent component) { this.Component = Enum.GetName(typeof(ULNComponent), component); } } 

派生的FileUploadAudit如下所示:

 public class FileUploadAudit : Audit { public FileUploadAudit(string message, ULNComponent component, Guid fileGuid, string originalFilename, string physicalFilename, HttpPostedFileBase postedFile) : base(message, component) { this.FileGuid = fileGuid; this.OriginalFilename = originalFilename; this.PhysicalFileName = physicalFilename; this.PostedFile = postedFile; this.ValidationErrors = new List(); } public Guid FileGuid { get; set; } public string OriginalFilename { get; set; } public string PhysicalFileName { get; set; } public HttpPostedFileBase PostedFile { get; set; } public IList ValidationErrors { get; set; } } 

有什么想法是什么问题? 我能找到的最接近的问题是我的,但我的部分Audit类在生成的代码中调用无参数构造函数,我仍然遇到问题。

更新:

只有当我传入派生的FileUploadAudit类时,才会出现此问题,Audit类工作正常。 Audit类是作为linq to sql类生成的,并且没有属性映射到派生类中的数据库字段。

经过一番研究后,我得出的结论是,没有简单的方法可以解决直接提交inheritance对象的问题。 映射inheritance层次结构是可能的,但这与您假装的内容无关。 您只想提交base class ,而不关心它是否实际上是派生class

如果您不想使用partial class向表类添加其他属性或行为,正如您提到的主题中所建议的那样,我会做一个简单的Clone方法作为变通方法:

  public partial class Audit { // ... public Audit Concrete() { if (this.GetType().Equals(typeof(Audit))) return this; else { Audit audit = new Audit(); // clone properties return audit; } } } //... dataContext.Audits.InsertOnSubmit(audit.Concrete()); 

尝试创建一个只有属性ID和typeDiscriminator的基本抽象类; 之后创建从基础inheritance的具体类,最后inheritance自最后一个类的其他类。 不要在已在基类中提供的派生类中包含属性。

示例:假设一个名为BasePeoples的基本抽象类具有属性ID和typeDiscriminator,我们有一个inheritance自基类的Person类和另外两个inheritancePerson类型的Fisherman和Driver类。

所以你将能够做到这样的事情

 using (DatabaseDataContext db = new DatabaseDataContext()) { Person p = new Person(); p.FirstName = "Dario"; p.LastName = "Iacampo"; Fisherman f = new Fisherman(); f.FirstName = "San"; f.LastName = "Pei"; f.CollectedFishes = 10; f.FishingLicenceNumber = "abc"; Driver d = new Driver(); d.FirstName = "Michael"; d.LastName = "Shumaker"; d.CarMake = "Ferrari"; d.DrivingLicenceNumber = "123abc"; db.BasePeoples.InsertOnSubmit(f); db.BasePeoples.InsertOnSubmit(d); db.SubmitChanges(); } 

如果您只想预先配置内容,则inheritance的替代方法可能是:

 partial class MyLinqClass { string Text = "Default"; public MyLinqClass AsOne() { Text = "One"; ... return this; } } var x = new MyLinqClass().AsOne(); context.InsertOnSubmit(x); // x is type MyLinqClass