ParentRelations not working on generated datasets?

I created two tables:

Publisher

  • PK, PublisherId, int, not null, indentity +1
  • PublisherName, varchar (50), not null

product

  • PK, ProductId, int, not null, identity +1
  • ProductName, varchar (50), not null
  • PublisherId, int, but not null

Then I created a foreign key constraint FK__Product__Publisher between the tables associated with PublisherId's.

Thus, I want to support products that have one Publisher each, while each publisher can have multiple products. It is so simple.

Now I have created a console project in C #, added a typed dataset and two TableAdapters. One indicates one publisher per product. The DataSet-Designer automatically adds a relationship based on what it receives from SQL Server.

It will also automatically generate properties that will allow me to access the publisher from the selected product and all products from the selected publisher.

This is my test code:

ProductTableAdapter adapter = new ProductTableAdapter();

foreach (ProductRow product in adapter.GetData())
{
    Console.WriteLine(product.PublisherRow.PublisherName);
}

      

However, this doesn't work. The generated code for the PublisherRow property looks like this:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public LanguageRow PublisherRow {
    get {
        return ((PublisherRow)(this.GetParentRow(this.Table.ParentRelations["FK_Product_Publisher"])));
    }
    set {
        this.SetParentRow(value, this.Table.ParentRelations["FK_Product_Publisher"]);
    }
}

      

this.Table.ParentRelations does not contain a relationship. It is zero and accessing it throws a NullReferenceException.

What am I doing wrong here?

0


source to share


1 answer


Seems a little odd when answering my own post. This is a bit like a conversation. However, I found a solution, and since this problem seems to be quite common, I am posting it here.

Just using TableAdapters to get the data will not get the correct relationship from the database. Relationships are initialized in the dataset class (namely, the InitClass method, which is called from the c'tor datasets):

public DbDataSet() {
    this.BeginInit();
    this.InitClass();
    ...
    this.EndInit();
}

      

The corresponding generated InitClass method looks like this:



private void InitClass() {
    ...
    this.relationFK_Product_Publisher= new global::System.Data.DataRelation("FK_Product_Publisher", new global::System.Data.DataColumn[] { this.tableProduct.PublisherIdColumn}, new global::System.Data.DataColumn[] { this.tablePublisher.PublisherIdColumn}, false);
    this.Relations.Add(this.relationFK_Product_Publisher);
}

      

This is why you need to instantiate the class of the dataset itself and use the fill method to populate your table classes like this:

DbDataSet ds = new DbDataSet();    

ProductTableAdapter productAdapter = new ProductTableAdapter();            
productAdapter.Fill(ds.Product);

PublisherTableAdapter publisherAdapter = new PublisherTableAdapter();
publisherAdapter.Fill(ds.Publisher);

foreach (ProductRow product in ds.Product)
{                
    Console.WriteLine(product.PublisherRow.PublisherName);
}

      

+2


source







All Articles