2015-02-07 20 views
7

Utknąłem z tym problemem od kilku wieczorów. Mam bazę danych SQLite w mojej aplikacji. Stworzyłem SQLite DB z pliku. Diagram ERD znajduje się poniżej: enter image description hereSQLite - pobieranie danych przy użyciu LINQ

A teraz w mojej aplikacji utworzyć połączenie do mojej bazy danych:

using (var conn = new SQLiteConnection(DB_PATH)) 
{ 
    // retrieving statemets... 
} 

stworzyłem klas, które reprezentują tabele w moim DB:

public class Kantory 
    { 
     public Kantory() 
     { 
      this.kursy = new HashSet<Kursy>(); 
     } 

     [SQLite.PrimaryKey, SQLite.AutoIncrement] 
     public int id_kantory { get; set; } 
     public string nazwa { get; set; } 

     public virtual ICollection<Kursy> kursy { get; set; } 
    } 

public class Waluty 
    { 
     public Waluty() 
     { 
      this.kursy = new HashSet<Kursy>(); 
     } 

     [SQLite.PrimaryKey, SQLite.AutoIncrement] 
     public int id_waluty { get; set; } 
     public string nazwa { get; set; } 

     public virtual ICollection<Kursy> kursy { get; set; } 
    } 

public class Kursy 
    { 
     [SQLite.PrimaryKey, SQLite.AutoIncrement] 
     public int id_kursy { get; set; } 
     public int id_kantory { get; set; } 
     public int id_waluty { get; set; } 
     public decimal kurs { get; set; } 
     public System.DateTime data { get; set; } 
     public int aktualne { get; set; } 

     public virtual Kantory kantory { get; set; } 
     public virtual Waluty waluty { get; set; } 
    } 

Jak widać, w tabeli kursy mam dwa klucze obce - id_kantory i id_waluty.

A teraz bardzo ciekawa i dziwna rzecz dzieje się. Kiedy próbuję odzyskać informacje za pomocą zwykłych statemets SQL z INNER JOIN oświadczenia - to działa dobrze !:

using (var conn = new SQLiteConnection(DB_PATH)) 
{ 
    var query = new SQLiteCommand(conn); 
    query.CommandText = "SELECT * FROM Kursy INNER JOIN Kantory ON Kursy.id_kursy=Kantory.id_kantory WHERE Kantory.id_kantory = 1"; 
    var result = query.ExecuteQuery<Kursy>(); 
} 

Ten kod działa poprawnie! Ale gdy próbuję użyć moich klas przy użyciu LINQ tak:

using (var conn = new SQLiteConnection(DB_PATH)) 
{ 
    var result = conn.Table<Kursy>().Where(k => k.kantory.id_kantory == 1).FirstOrDefault(); 
} 

To rzuca mi NotSupportedException! messsage to: dostęp Użytkownik nie udało się skompilować wyraz

ale kiedy używam moje zajęcia z wykorzystaniem LINQ bez łączenia inna klasa działa !:

using (var conn = new SQLiteConnection(DB_PATH)) 
    { 
     var result = conn.Table<Kursy>().Where(k => k.id_kursy == 1).FirstOrDefault(); 
    } 

Więc w końcu: mój problem jest to Nie mogę dołączyć więcej do tej tabeli przy użyciu zapytania LINQ. Wydaje się, że ten model na zajęciach jest błędny, ale naprawdę nie wiem dlaczego ...

PS. Jest to aplikacja Windows Phone 8.1, więc nie mogę użyć do tego Struktury Entity.

+1

Sqlite-net nie obsługuje kluczy obcych – ErikEJ

+0

@ErikEJ, hmm, ale kiedy używam zwykłej instrukcji SQL, jak pokazano powyżej, używając 'SELECT ... FROM ... INNER JOIN ...' to działa. Więc prawdopodobnie używa obcych kluczy, prawda? – XardasLord

+2

Nie tłumaczy sprzężeń od LINQ do SQL – ErikEJ

Odpowiedz

7

Oto kod, który działa. Używa tylko EntityFramework 6.3.1 bez żadnych specyficznych zestawów SQLite.

Rozumiem, że NIE chcesz używać Entity Framework. Aby dodać odpowiedź na to pytanie, musimy znać konkretne zestawy, z których korzystasz. Na przykład, czy używasz DbLinq?

W szczególności, jakie zespoły zawierają następujące metody?

  • SQLiteCommand.ExecuteQuery<T>()
  • SQLiteConnection.Table<T>()

W każdym razie, tutaj jest kod, który działa z Entity Framework.

using System; 
using System.Linq; 
using System.Data.Entity; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 

namespace SQLite 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var conn = new SQLiteConnection(@"C:\linqToSqlite.db")) 
      { 
       SeedEntities(conn); 

       // this is the query that DID work for you 
       var result1 = conn.Kursy 
        .Where(k => k.id_kursy == 1) 
        .FirstOrDefault(); 

       Console.WriteLine(
        string.Format("id_kursy:{0}", result1.id_kursy)); 

       // this is the query that did NOT work for you 
       // it does work here 
       var result2 = conn.Kursy 
        .Where(k => k.kantory.id_kantory == 1) 
        .FirstOrDefault(); 

       Console.WriteLine(
        string.Format("id_kursy:{0}", result2.id_kantory)); 
      } 

      Console.ReadKey(); 
     } 

     private static void SeedEntities(SQLiteConnection conn) 
     { 
      SeedEntities(conn); 
      // make sure two entities exist with the appropriate ids 
      if (!conn.Kantory.Any(x => x.id_kantory == 1)) 
      { 
       conn.Kantory 
        .Add(new Kantory() { id_kantory = 1 }); 
      } 

      if (!conn.Kursy.Any(x => x.id_kantory == 1)) 
      { 
       conn.Kursy 
        .Add(new Kursy() { id_kantory = 1 }); 
      } 

      conn.SaveChanges(); 
     }   
    } 

    public class SQLiteConnection : DbContext 
    { 
     public SQLiteConnection(string connString) : 
      base(connString) {} 
     public DbSet<Kantory> Kantory { get; set; } 
     public DbSet<Kursy> Kursy { get; set; } 
    } 

    public class Kantory 
    { 
     public Kantory() 
     { 
      this.kursy = new HashSet<Kursy>(); 
     } 

     [Key] 
     public int id_kantory { get; set; } 
     public virtual ICollection<Kursy> kursy { get; set; } 
    } 

    public class Kursy 
    { 
     [Key] 
     public int id_kursy { get; set; } 
     public int id_kantory { get; set; } 
     public virtual Kantory kantory { get; set; } 
    } 
} 

Obawiam się, że użył innej techniki niż ty, bo nie wiem dokładnie zespoły zostały użyte. Na przykład nie było jasne, który zestaw został użyty do metody Table<T>().Więc użyłem podejście DbContext.Kursy zamiast i następujących dokumentów:

  • EntityFramework.dll
  • EntityFramework.SqlServer.dll
  • System.dll
  • System.ComponentModel.DataAnnotations.dll

Innymi słowy, to działa tylko z EntityFramework 6.1.3 i nie wymaga żadnych konkretnych zestawów.

Aby uzyskać odpowiedź, która jest odpowiednia do Twoich potrzeb, do jakich odniesień odwołujesz się w przypadku konkretnych referencji?

+0

Dzięki! W moim przypadku nie ustawiłem moich właściwości FK jako wirtualnych, a LINQ ich nie wypełniało. na przykład 'public string Colour_Id {get; zestaw; } [ForeignKey ("Colour_Id")] publiczny wirtualny kolor Color {get; zestaw; } ' – Kris

Powiązane problemy