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; }
}

問題は何ですか?私が見つけることができる最も近い質問はhere ですが、私の部分的な Audit クラスは、生成されたコードでパラメーターなしのコンストラクターを呼び出していますが、それでも問題が発生します。

アップデート:

この問題は、派生した FileUploadAudit クラスを渡した場合にのみ発生し、Audit クラスは正常に動作します。Audit クラスは linq to sql クラスとして生成され、派生クラスのデータベース フィールドにマップされたプロパティはありません。

4

3 に答える 3

3

少し調査した結果、継承されたオブジェクトを直接送信するというこの問題を簡単に解決する方法はないという結論に達しました。継承階層をマップすることは可能ですが、これはあなたのふりとは何の関係もありません。を送信したいだけでbase class、それが実際に派生したものであるかどうかは気にしませんclass

あなたが言及したスレッドpartial classで示唆されているように、追加のプロパティや動作をテーブル クラスに追加するために a を使用したくない場合は、回避策として単純な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のみを持つ基本抽象クラスを作成してみてください。その後、ベースから継承する具象クラスを作成し、最終的には最後のクラスから継承する他のクラスを作成します。ベース1にすでに存在する派生クラスにプロパティを含めないでください。

例:プロパティIDとtypeDiscriminatorを持つBasePeoplesという名前の基本抽象クラスを想定すると、基本から継承するタイプPersonのクラスと、フォームPersonを継承するタイプFishermanとDriverの2つのクラスがあります。

だからあなたはこのようなことをすることができるでしょう

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 に答える