我正在尝试使用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<IExceptionHandler>().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<string>();
}
public Guid FileGuid { get; set; }
public string OriginalFilename { get; set; }
public string PhysicalFileName { get; set; }
public HttpPostedFileBase PostedFile { get; set; }
public IList<string> ValidationErrors { get; set; }
}
任何想法是什么问题?我能找到的最接近的问题是here,但我的部分Audit类在生成的代码中调用无参数构造函数,我仍然遇到问题。
更新
只有当我传入派生的FileUploadAudit类时才会出现此问题,Audit类工作正常。 Audit类是作为linq to sql类生成的,并且没有属性映射到派生类中的数据库字段。
答案 0 :(得分:3)
经过一番研究后,我得出的结论是,没有简单的方法可以解决直接提交继承对象的问题。有可能Map Inheritance Hierarchies但这与你假装的内容无关。您只想提交base
class
,而不关心它是否实际上是派生的class
。
如果您不想使用partial class
向表类添加其他属性或行为,正如您提到的thread中所述,我会做一个简单的克隆< / em>方法作为解决方法:
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());
答案 1 :(得分:0)
尝试创建一个只有属性ID和typeDiscriminator的基本抽象类;之后创建从基础继承的具体类,最后继承自最后一个类的其他类。 不要在已在基类中出现的派生类中包含属性。
示例:假设一个名为BasePeoples的基本抽象类具有属性ID和typeDiscriminator,我们有一个继承自基类的Person类和另外两个继承Person类型的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();
}
答案 2 :(得分:0)
如果您只想预先配置内容,则继承的替代方法可能是:
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