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

时间:2009-10-15 12:58:04

标签: c# .net linq-to-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<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类生成的,并且没有属性映射到派生类中的数据库字段。

3 个答案:

答案 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