2

我正在尝试使用 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; }
}

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

更新:

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

4

3 回答 3

3

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

如果您不想使用 apartial 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());
于 2009-10-15T15:03:16.580 回答
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();

        }
于 2010-03-20T14:06:40.523 回答
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
于 2010-10-06T20:04:46.157 回答