2013-04-04 4 views
8

Mam blok kodu, który próbuje kwerendy niektóre proste parametry konfiguracyjne z bazy danych. Jednak korzystając z poniższego kodu, jak tylko wyliczyć wynik pojawia się pierwsza wartość dla każdego elementu w wyniku:Dlaczego iteracja po IQueryable daje pierwszą wartość dla każdego elementu w wyniku?

var db = new ConfigurationServiceDataContext("Server=vsdcs022.aridev.lcl;Database=ConfigurationService;Trusted_Connection=True;"); 

var parameters = 
    from configContents in db.ConfigurationContents 
    where 
     configContents.ConfigurationContextsTable.ConfigurationContextName == contextName && 
     configContents.ConfigurationSectionTable.ConfigurationSectionName == sectionName 
    select configContents; 

// print stuff for debugging purposes: 
foreach (var parameter in parameters) 
{ 
    Console.WriteLine("key = '{0}', value = '{1}'", parameter.ConfigurationKey, parameter.ConfigurationValue); 
} 

return parameters.ToDictionary(parameter => parameter.ConfigurationKey, parameter => parameter.ConfigurationValue); 

Gdybym wydrukować wyniki (przed przystąpieniem, aby dodać je do nowego słownika) I coś takiego:

key = 'key1', value = 'value1' 
key = 'key1', value = 'value1' 
key = 'key1', value = 'value1' 

Ale jeśli mogę wymienić wybierz linię typu anonimowego , to działa dobrze:

select new { configContents.ConfigurationKey, configContents.ConfigurationValue }; 

z tego anonimowy typ, pojawia się następujący wynik:

key = 'key1', value = 'value1' 
key = 'key2', value = 'value2' 
key = 'key3', value = 'value3' 

mam zbadane to na kilka godzin teraz bezskutecznie a jednocześnie może po prostu nazwać to dobry z anonimowego typu, to jest naprawdę mnie niepokoi. Widziałem mnóstwo przykładów, które sugerują, że mój pierwszy blok kodu powinien działać dobrze. Jestem pewien, że robię coś głupiego, po prostu tego nie widzę!

Wszelkie pomysły?

Poniżej znajdują się pełne dane modelu używam począwszy od realizacji DataContext:

using System.Data.Linq; 
using Ari.Core.ConfigurationService.LinqEntityClasses; 

namespace Ari.Core.ConfigurationService 
{ 
    class ConfigurationServiceDataContext : DataContext 
    { 
     public Table<ConfigurationContentsTable> ConfigurationContents; 
     public Table<ConfigurationContextsTable> ConfigurationContexts; 
     public Table<ConfigurationSectionsTable> ConfigurationSections; 

     public ConfigurationServiceDataContext(string connectionString) : base(connectionString) {} 
    } 
} 

tabela zawiera rdzeń jest reprezentowana przez mojego ConfigurationContentsTable klasy jednostki:

using System.Data.Linq; 
using System.Data.Linq.Mapping; 

namespace Ari.Core.ConfigurationService.LinqEntityClasses 
{ 
    [Table(Name = "ConfigurationContents")] 
    class ConfigurationContentsTable 
    { 
     private long _configurationContextId; 
     private string _configurationKey; 
     private string _configurationValue; 
     private EntityRef<ConfigurationContextsTable> _configurationContextsTable; 
     private EntityRef<ConfigurationSectionsTable> _configurationSectionsTable; 

     public ConfigurationContentsTable() 
     { 
      _configurationContextsTable = new EntityRef<ConfigurationContextsTable>(); 
      _configurationSectionsTable = new EntityRef<ConfigurationSectionsTable>(); 
     } 

     [Column(Storage = "_configurationContextId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, 
      IsDbGenerated = true)] 
     public long ConfigurationContextId 
     { 
      get { return _configurationContextId; } 
     } 

     [Column(Storage = "_configurationKey")] 
     public string ConfigurationKey 
     { 
      get { return _configurationKey; } 
      set { _configurationKey = value; } 
     } 

     [Column(Storage = "_configurationValue")] 
     public string ConfigurationValue 
     { 
      get { return _configurationValue; } 
      set { _configurationValue = value; } 
     } 

     [Association(Storage = "_configurationContextsTable", OtherKey = "ConfigurationContextId")] 
     public ConfigurationContextsTable ConfigurationContextsTable 
     { 
      get { return _configurationContextsTable.Entity; } 
      set { _configurationContextsTable.Entity = value; } 
     } 

     [Association(Storage = "_configurationSectionsTable", OtherKey = "ConfigurationSectionId")] 
     public ConfigurationSectionsTable ConfigurationSectionTable 
     { 
      get { return _configurationSectionsTable.Entity; } 
      set { _configurationSectionsTable.Entity = value; } 
     } 
    } 
} 

Dwa powiązane tabele są dość proste i istnieją tylko w celu normalizacji. Są one reprezentowane przez następujące osoby:

using System.Data.Linq; 
using System.Data.Linq.Mapping; 

namespace Ari.Core.ConfigurationService.LinqEntityClasses 
{ 
    [Table(Name = "ConfigurationContexts")] 
    class ConfigurationContextsTable 
    { 
     private long _configurationContextId; 
     private string _configurationContextName; 
     private EntityRef<ConfigurationContentsTable> _configurationContentsTable; 

     public ConfigurationContextsTable() 
     { 
      _configurationContentsTable = new EntityRef<ConfigurationContentsTable>(); 
     } 

     [Column(Storage = "_configurationContextId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, 
      IsDbGenerated = true)] 
     public long ConfigurationContextId 
     { 
      get { return _configurationContextId; } 
     } 

     [Column(Storage = "_configurationContextName")] 
     public string ConfigurationContextName 
     { 
      get { return _configurationContextName; } 
      set { _configurationContextName = value; } 
     } 

     [Association(Storage = "_configurationContentsTable", ThisKey = "ConfigurationContextId")] 
     public ConfigurationContentsTable ConfigurationContentsTable 
     { 
      get { return _configurationContentsTable.Entity; } 
      set { _configurationContentsTable.Entity = value; } 
     } 
    } 
} 

I wreszcie:

using System.Data.Linq; 
using System.Data.Linq.Mapping; 

namespace Ari.Core.ConfigurationService.LinqEntityClasses 
{ 
    [Table(Name = "ConfigurationSections")] 
    class ConfigurationSectionsTable 
    { 
     private long _configurationSectionId; 
     private string _configurationSectionName; 
     private EntityRef<ConfigurationContentsTable> _configurationContentsTable; 

     public ConfigurationSectionsTable() 
     { 
      _configurationContentsTable = new EntityRef<ConfigurationContentsTable>(); 
     } 

     [Column(Storage = "_configurationSectionId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, 
      IsDbGenerated = true)] 
     public long ConfigurationSectionId 
     { 
      get { return _configurationSectionId; } 
     } 

     [Column(Storage = "_configurationSectionName")] 
     public string ConfigurationSectionName 
     { 
      get { return _configurationSectionName; } 
      set { _configurationSectionName = value; } 
     } 

     [Association(Storage = "_configurationContentsTable", ThisKey = "ConfigurationSectionId")] 
     public ConfigurationContentsTable ConfigurationContentsTable 
     { 
      get { return _configurationContentsTable.Entity; } 
      set { _configurationContentsTable.Entity = value; } 
     } 
    } 
} 
+2

Dobre pytanie! Opublikuj swój kod "wydrukuj wyniki" (Twój kod wygląda dobrze, w chwili, w której podejrzewam, że uzyskujesz dostęp do zmodyfikowanego zamknięcia w kodzie drukowania). –

+0

Czy możesz umieścić kod, który wypisze (niepoprawne) wyniki? – Rob

+1

Pachnie jak zmodyfikowane zamknięcie. – ken2k

Odpowiedz

0

Więc po więcej kopania i przeglądu mojego kodu, znalazłem dwa problemy, które, kiedy poprawione, otrzymując oczekiwany rezultat.

Po pierwsze, w mojej klasie obiektów ConfigurationContentsTable moje pole PK zostało skonfigurowane tak, aby patrzeć na pole ConfigurationContextId zamiast na pole ConfigurationContentId. Kiedy to naprawiłem, zacząłem uzyskiwać tylko jeden wynik, gdy spodziewałem się trzech. To skłoniło mnie do spojrzenia na logikę asocjacji tabeli/łączenia (patrz drugi element poniżej). Poprawione fragment kodu w ConfigurationContentsTable:

[Column(Storage = "_configurationContentId", DbType = "BigInt NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)] 
public long ConfigurationContentId 
{ 
    get { return _configurationContentId; } 
} 

Po drugie, dla wszystkich EntityRef <> właściwości z atrybutami [Association(Storage = ...], miałem ThisKey i OtherKey właściwości odwrócone. Po zmianie elementu ConfigurationContentsTable w celu użycia ThisKey i tabeli ConfigurationContextsTable i ConfigurationSectionsTable do użycia OtherKey, zacząłem widzieć oczekiwane trzy różne wyniki.

kod Poprawione dla ConfigurationContentsTable:

[Association(Storage = "_configurationContextsTable", ThisKey = "ConfigurationContextId")] 
public ConfigurationContextsTable ConfigurationContextsTable 
{ 
    get { return _configurationContextsTable.Entity; } 
    set { _configurationContextsTable.Entity = value; } 
} 

[Association(Storage = "_configurationSectionsTable", ThisKey = "ConfigurationSectionId")] 
public ConfigurationSectionsTable ConfigurationSectionsTable 
{ 
    get { return _configurationSectionsTable.Entity; } 
    set { _configurationSectionsTable.Entity = value; } 
} 

kod Poprawione dla ConfigurationContextsTable:

[Association(Storage = "_configurationContentsTable", OtherKey = "ConfigurationContextId")] 
public ConfigurationContentsTable ConfigurationContentsTable 
{ 
    get { return _configurationContentsTable.Entity; } 
    set { _configurationContentsTable.Entity = value; } 
} 

I wreszcie poprawiony kod ConfigurationSectionsTable:

[Association(Storage = "_configurationContentsTable", OtherKey = "ConfigurationSectionId")] 
public ConfigurationContentsTable ConfigurationContentsTable 
{ 
    get { return _configurationContentsTable.Entity; } 
    set { _configurationContentsTable.Entity = value; } 
} 
+0

Wpadłem na ten problem, ponieważ ręcznie stworzyłem klasy jednostek Linq. Uniknęłabym tego problemu, gdyby po prostu dodałem element "LINQ to SQL Classes", który tworzy powierzchnię projektu dbml, na której można przeciągnąć połączenie z bazą danych (z eksploratora serwera). Zrób to automatycznie generując dla ciebie wszystkie klasy jednostek. – Sam

Powiązane problemy