This project is read-only.

INSERT conflict with FOREIGN KEY constraint

Oct 5, 2010 at 12:35 AM

Seeding my new database with some data as follows: 

 

Administrator.NewDatabaseBasic();

StratumDN Morphemic = new StratumDN();

Morphemic.RefName ="Morphemic";

Morphemic.ShortName ="M";

Database.Save<StratumDN>(Morphemic);

 

// preload morphemic the

EmeDN Mthe = new EmeDN();

Mthe.RefName ="Mthe";

Mthe.IsOn = Morphemic;

Database.Save<EmeDN>(Mthe);

Morphemic.HasOnIt =new MList<StratObjectDN>();

Morphemic.HasOnIt.Add(Mthe);

Database.Save<StratumDN>(Morphemic);

When I try to save the Morphemic stratum entity after adding 'the' to its list of Morphemes, I get the following error:

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_trtlStratumDNHasOnIt_idStratObjectDN". The conflict occurred in database "C:\DOCUMENTS (etc) .MDF", table "dbo.tlStratObjectDN", column 'Id. The statement has been terminated.

A Stratum can have several kinds of objects on it, not just emes. So each object that it can have (including EmeDN) inherits from StratObjectDN. Specifically, they all inherit the RefName field which is nonnullable.

I tried a simple example of inheritance and bi-reference on the example database and did not get this error. Any ideas as to what might be wrong? 

Oct 5, 2010 at 9:23 AM

Hi Hezek1ah, 

The enphasis on the way Signum Framework deals with inheritance is in the foreing key. You have to decorate with an attribute ImplementedBy (and enumerate the possible concrete classes) the field you want to have inheritance behaviour, in the database many columns will be created, on FK for each concrete type. 

The field could be just a reference o an entity, a Lazy, an MList of references or an MList of Lazies. You can see more info here http://signumframework.com/Inheritance.ashx

On the other side, we differ from  other ORMs in the way we deal with 1 to many relatoionships: Here you have to choose between SaturnDN having an MList<EmeDN>, or EmeDN having a reference to SaturnDN, Having both creates a redundant relationship!!!. You will have to choose one and use LINQ queries for transversing the relationship in the other direction. 

Maybe this looks unconvinient at the begining but there's a good reason for that: The rest of the ORMS, like LINQ to Entityes, etc.. create ciclic dependencies between almost any two related entities in the database.,making it impossible to sepparate them in different assemblies and re-use pars of code. 

Hope it helps.

Some notes: 
* Save is an extension method and u can use type inference, so instead of Database.Save<EmeDN>(Mthe) --> Mthe.Save()
* Its not considered a good practice declaring local variables with uppercase in .Net
* You can also use object initializers more intensively:

//first u decorate the property

[ImplementedBy(typeof(StratumDN), ...)]
StratObject isOn;
public StartObject IsOn
{
   get{ return isOn; }
   get{ Set(ref isOn, value, "IsOn"); } 
}


//Second create the schema

Administrator.NewDatabaseBasic();
StratumDN morphemic = new StratumDN()
{
    RefName ="Morphemic",
    ShortName ="M",
}.Save(); 


EmeDN mthe = new EmeDN()
{ 
    RefName = "Mthe", 
    IsOn = morphemic 
}.Save();


//You can retrieve all the EmeDN pointing to morphemic like this:

List<EmeDN> emes = Database.Query<EmeDN>().Where(m=>m.IsOn == morpemic).ToList();