在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