设置自引用类

时间:2013-07-18 09:38:37

标签: c# sql linq linq-to-sql windows-phone-8

我有一个递归数据结构,它有一个(可为空的)父类和一个(可为空的)子集合。

我想将该数据结构保存到Windows Phone上的本地数据库中。 我设置了一个相当不错的DataContext,但是当我想插入一个新对象(没有父对象)时,我得到“对象引用未设置为对象的实例”。错误。

搜索之后,我发现这个线程LINQ to SQL: Self-referencing entity - ParentID/ChildID association并且它声明由于父对象和子对象为空而抛出此异常。 但由于这是一个允许的状态,这不应该阻止我的代码正常运行。

所以问题是:如何建立一个自我引用类。

到目前为止我做了什么:

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

有人可以告诉我,我如何使用或更改Associoaton - 属性,以便我可以将可以为空的父母和孩子插入我的数据库?

2 个答案:

答案 0 :(得分:1)

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。使用与getter相同的检查来防止此问题:

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

this.children.Assign(value);

答案 1 :(得分:0)

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

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

    [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