VirtueMart Manager: VirtueMart Price Updater czyli LINQ z MySQL przy pomocy DB_Linq
Jeden z moich klientów korzysta z systemu Joomla i dodatku VirtueMart (moduł sklepu internetowego). Żeby uprościć jego obsługę pomyślałem nad napisaniem aplikacji do aktualizacji cen pobieranych z jakiegoś źródła.
Aplikacja korzysta z DB_Linq czyli Linq Provider for MySql, Oracle and PostgreSQL. Niestety DB_Linq nie ma aktualnie żadnej dokumentacji. Za to znalazłem drobne informacje na stronie Primary Objects. Wykorzystałem wersję 0.18 która jest deprecated ponieważ z 0.19 miałem problem z wygenerowaniem klas linq.
Z wersją 0.18 też był problem…
DbMetal failed:System.ArgumentException: magma string must not be empty
Okazało się, że jest problem jeśli nazwy tabel w bazie zawierają obok siebie dwa znaki podkreślenia.
Oczywiście pogrzebałem trochę w kodzie i to sobie poprawiłem:
1: 2: //\DbLinq-0.18\src\DbLinq\Language\Implementation\AbstractWords.cs, linia 139
3: public virtual IList<string> GetWords(string text)
4: {5: text = text.Replace("__", "_"); //zamienia dwa podkreślenia na jedno
6: Teraz mogłem już zacząć korzystać z zalet linq połączonego z bazą MySQL.
Dla tych którzy nie znają angielskiego (lub nie lubią czytać po angielsku) napiszę co po koli należy zrobić aby łatwo pogrzebać sobie w bazie MySQL.
- Ściągnąć DB_Linq
- Wygenerować klasy modelu na podstawie struktury bazy danych. Zostanie utworzony jeden plik o nazwie takiej samej jak nazwa bazy.
1: dbmetal /server:1.2.3.4 /user:dbuser /password:password /provider:MySql /database:people /language:C# - To wszystko :)
Klasy mamy gotowe więc można operować na bazie.
Odczytywanie danych z bazy (SELECT).
1: public ObservableCollectionGetProducts()
2: {3: using (var connection = new MySqlConnection("server=server.pl;user id=user; password=haslo; database=baza"))
4: { 5: connection.Open();6: using (var dataContext = new BazaDataContext(connection))
7: { 8: 9: var items = from s in dataContext.JoSVMProduct
10: join pc in dataContext.JoSVMProductPrice on s.ProductID equals pc.ProductID
11: orderby s.ProductName ascending12: select new ProduktVm
13: { 14: ProductId = s.ProductID, 15: ProductSku = s.ProductSku, 16: ProductName = s.ProductName, 17: ProductPrice = pc.ProductPrice, 18: ProductFullImage = s.ProductFullImage, 19: }; 20: 21: var collection = new ObservableCollection();
22: foreach (var c in items)
23: collection.Add(c); 24: 25: return collection;
26: } 27: } 28: }W powyższym przykładzie pobieram dane o produktach i cenach i tworzę sobie obserwowalną kolekcję. ProduktVm to moja klasa pośrednia.
Aktualizowanie danych w bazie (UPDATE).
1: using (var conn = new MySqlConnection("server=server.pl;user id=user; password=haslo; database=baza"))
2: { 3: conn.Open();4: using (var context = new BazaDataContext(conn))
5: {6: var items = from pc in context.JoSVMProductPrice
7: where pc.ProductID == 1
8: select pc; 9: var i = items.First(); 10: i.ProductPrice = -1; 11: context.SubmitChanges(); 12: } 13: }Dodawanie danych do bazy (INSERT).
1: using (PeopleDataContext context = new PeopleDataContext(connection))
2: {3: // Create a LINQ to SQL class to fill the properties.
4: Person person = new Person();
5: person.FirstName = txtFirstName.Text; 6: person.LastName = txtLastName.Text; 7: person.Age = Convert.ToInt32(txtAge.Text); 8: 9: context.Person.InsertOnSubmit(person); 10: context.SubmitChanges(); 11: } W mojej aplikacji jeszcze insertów nie robię więc podaję przykład z Primary Objects
Na koniec dodam jeszcze, że VMManager miał pobierać dane z Excela, ale niestety nie znalazłem żadnego działającego sposobu pobrania danych z arkusza. Zapisałem arkusz jako plik tekstowy z danymi rozdzielonymi znakami tabulacji i takie dane to już da się odczytać.


