1

I have a recursive data structure, which has a (nullable) parent and a (nullable) collection of children.

I want to save that data structure into a local database on windows phone. I set up a DataContext which works rather nicely, but when I want to insert a new object (which has no parent neither children), I get the "Object reference not set to an instance of an object." error.

After searching, I found this thread LINQ to SQL: Self-referencing entity - ParentID/ChildID association and it states, that this exception is thrown because of the parent and children objects being null. But as this is an allowed state, this should not prevent my code from running properly.

So the question is: how to set up a self referncing class.

What I have done so far:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

namespace Notepad.Codes.Models
{

    [Table]
    public class DirectoryItem 
    {
        [Column(IsVersion=true)]
        private Binary version;

        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public int primaryKey;

        private DirectoryItem parent;
        [Association(Storage = "parent", ThisKey = "primaryKey", OtherKey = "primaryKey")]
        public DirectoryItem Parent
        {
            get
            {
                return parent;
            }
            set
            {
                this.SetProperty(ref this.parent, value);
            }
        }

        private EntitySet<DirectoryItem > children;
        [Association(Storage = "children", OtherKey = "primaryKey")]
        public EntitySet<DirectoryItem > Children
        {
            get
            {
                if( children == null)
                    children = new EntitySet<DirectoryItem >();
                return children;
            }
            set
            {
                if (this.PropertyChanging != null)
                    PropertyChanging(this, new PropertyChangingEventArgs("Children"));
                this.children.Assign(value);
                if (this.PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("Children"));
            }
        }
    }
}

Could somebody please tell me, how I have to use or change the Associoaton-Attribute so that I can insert nullable parents and children into my database?

4

2 回答 2

1

属性的setter有问题Children

if (this.PropertyChanging != null)
    PropertyChanging(this, new PropertyChangingEventArgs("Children"));

this.children.Assign(value);

if (this.PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs("Children"));

this.children.Assign即使children可能未初始化,您仍在调用。使用与您的吸气剂相同的检查来防止此问题:

if( children == null)
    children = new EntitySet<DirectoryItem >();

this.children.Assign(value);
于 2013-07-18T11:46:23.777 回答
0

我用北风解决了我的问题。我遵循了这些步骤(我列出了它们,因为 MSDN 是一个变化很大的地方:)

  1. 转到http://www.microsoft.com/en-us/download/details.aspx?id=23654
  2. 下载并运行安装程序
  3. 打开视觉工作室(<2012)
  4. 打开服务器资源管理器,打开数据连接的快捷菜单并选择添加连接
  5. 选择Microsoft SQL 服务器数据库文件
  6. 选择浏览并浏览到已安装的数据库(对我来说它安装在C:\Sample Database(或类似的)
  7. 使用Windows 身份验证并单击确定*
  8. 从 Northwind 数据库中选择所有表并将它们拖放到对象关系设计器中
  9. 现在您可以更改到文件后面的代码,并查看所有逻辑和属性

我的案例的解决方案现在看起来像:

[Table]
public class DirectoryItem 
{
    [Column(IsVersion=true)]
    private Binary version;

    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public int primaryKey;

    private System.Nullable<int> parentId;
    [Column(Storage = "parentId", DbType="Int")]
    public System.Nullable<int> ParentId
    {
        get
        {
            return this.parentId;
        }
        set
        {
            this.SetProperty(ref this.parentId, value);
        }
    }

    private EntityRef<DirectoryItem > parent;
    [Association(Name = "DirectoryItem_parent", Storage = "parent", ThisKey = "ParentId", OtherKey = "primaryKey", IsForeignKey = true)]
    public DirectoryItem Parent
    {
        get
        {
            return parent.Entity;
        }
        set
        {
            if (this.PropertyChanging != null)
                PropertyChanging(this, new PropertyChangingEventArgs("Parent"));

            parent.Entity = value;

            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Parent"));
        }
    }

    private EntitySet<DirectoryItem > children;
    [Association(Name = "DirectoryItem_DirectoryItem", Storage = "Children", ThisKey = "primaryKey", OtherKey = "ParentId")]
    public EntitySet<DirectoryItem > Children
    {
        get
        {
            if (children == null)
                children = new EntitySet<DirectoryItem >();
            return children;
        }
        set
        {
            if (this.PropertyChanging != null)
                PropertyChanging(this, new PropertyChangingEventArgs("Children"));

            if (children == null)
                children = new EntitySet<DirectoryItem >();
            this.children.Assign(value);

            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Children"));
        }
    }
}

附录:

  1. 安装示例数据库的说明:http: //msdn.microsoft.com/en-us/library/vstudio/8b6y4c7s.aspx
于 2013-07-19T07:45:35.230 回答