Родительские отношения не работают в сгенерированных DataSets? - PullRequest
0 голосов
/ 19 ноября 2008

Я создал две таблицы:

Издатель

  • PK, PublisherId, int, not null, indentity +1
  • PublisherName, varchar (50), не нуль

Продукт

  • PK, ProductId, int, не null, идентификатор + 1
  • ProductName, varchar (50), не нуль
  • PublisherId, int, not null

Затем я создал ограничение внешнего ключа FK__Product__Publisher между таблицами, связывающими PublisherId.

Таким образом, я хочу поддерживать Продукты с одним Издателем, в то время как каждый Издатель может иметь несколько Продуктов. Это так просто.

Теперь я создал консольный проект на C #, добавил типизированный набор данных и два TableAdapter. Один указывает на издателя один на продукт. DataSet-Designer автоматически добавляет отношение в зависимости от того, что он получает от SQL Server.

Он также автоматически генерирует свойства, которые позволят мне получить доступ к издателю из выбранного Продукта и ко всем продуктам из выбранного издателя.

Это мой тестовый код:

ProductTableAdapter adapter = new ProductTableAdapter();

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

Однако это не работает. Сгенерированный код, свойство PublisherRow выглядит так:

[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 не содержит отношения. Он имеет значение null, и при обращении к нему возникает исключение NullReferenceException.

Что я здесь не так делаю?

1 Ответ

2 голосов
/ 19 ноября 2008

Кажется немного странным отвечать на мой собственный пост. Это немного похоже на разговор с самим собой. Тем не менее, я вроде нашел решение, и, поскольку эта проблема кажется довольно распространенной, я выкладываю ее здесь.

Простое использование TableAdapters для получения данных не приведет к получению надлежащих отношений из базы данных. Инициализация отношений происходит внутри класса набора данных (а именно, метода InitClass, который вызывается из набора данных ctor):

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

Соответствующий сгенерированный метод InitClass выглядит следующим образом:

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

Вот почему вам нужно создать экземпляр самого класса набора данных и использовать метод fill для заполнения ваших табличных классов следующим образом:

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