English version - not all articles are translated
VirtueMart Manager: VirtueMart Price Updater czyli LINQ z MySQL przy pomocy DB_Linq
- Details
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:
//\DbLinq-0.18\src\DbLinq\Language\Implementation\AbstractWords.cs, linia 139 public virtual IList<string> GetWords(string text) { text = text.Replace("__", "_"); //zamienia dwa podkreślenia na jedno
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
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).
public ObservableCollection GetProducts() { using (var connection = new MySqlConnection("server=server.pl;user id=user; password=haslo; database=baza")) { connection.Open(); using (var dataContext = new BazaDataContext(connection)) { var items = from s in dataContext.JoSVMProduct join pc in dataContext.JoSVMProductPrice on s.ProductID equals pc.ProductID orderby s.ProductName ascending select new ProduktVm { ProductId = s.ProductID, ProductSku = s.ProductSku, ProductName = s.ProductName, ProductPrice = pc.ProductPrice, ProductFullImage = s.ProductFullImage, }; var collection = new ObservableCollection(); foreach (var c in items) collection.Add(c); return collection; } } }
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).
using (var conn = new MySqlConnection("server=server.pl;user id=user; password=haslo; database=baza")) { conn.Open(); using (var context = new BazaDataContext(conn)) { var items = from pc in context.JoSVMProductPrice where pc.ProductID == 1 select pc; var i = items.First(); i.ProductPrice = -1; context.SubmitChanges(); } }
Dodawanie danych do bazy (INSERT).
using (PeopleDataContext context = new PeopleDataContext(connection)) { // Create a LINQ to SQL class to fill the properties. Person person = new Person(); person.FirstName = txtFirstName.Text; person.LastName = txtLastName.Text; person.Age = Convert.ToInt32(txtAge.Text); context.Person.InsertOnSubmit(person); context.SubmitChanges(); }
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ć.