Reputation: 1844
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?
Upvotes: 1
Views: 4128
Reputation: 1844
I solved my problem with northwind. I followed these steps (I list them, because MSDN is a heavily changing place:)
C:\Sample Database
(or similar)And the solution for my case now looks like:
[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"));
}
}
}
Appedix:
Upvotes: 0
Reputation: 39007
There's a problem in the setter of the Children
property:
if (this.PropertyChanging != null)
PropertyChanging(this, new PropertyChangingEventArgs("Children"));
this.children.Assign(value);
if (this.PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Children"));
You're calling this.children.Assign
even though children
might not be initialized. Use the same check as your getter to prevent this issue:
if( children == null)
children = new EntitySet<DirectoryItem >();
this.children.Assign(value);
Upvotes: 1