myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Code-Reviews » Benutzung von LiteDB mit Abstraktionsschicht
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Benutzung von LiteDB mit Abstraktionsschicht

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
JimStark
myCSharp.de-Mitglied

avatar-1005.jpg


Dabei seit: 10.03.2020
Beiträge: 154
Entwicklungsumgebung: Visual Studio 6.0 Enterprise


JimStark ist offline

Benutzung von LiteDB mit Abstraktionsschicht

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

vielleicht kennt ja der ein oder andere  LiteDB.
Da ein SQL-Server für dieses Projekt zu aufwendig wäre, würde ich gerne eine lokale Datenbank einsetzen. Vielleicht kennt ja jemand auch eine bessere Alternative.

Ich nehme als Beispiel wieder eine kleine Auftragsverwaltung - Auftrag - Kunde - Artikel.

C#-Code:
    public class Article
    {
        public int ArticleID { get; set; }
        public string Title { get; set; }
        public Order Order { get; set; }
...

    public class Customer
    {
        public int CustomerID { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public List<Order> Orders { get; set; } = new List<Order>();
...
    public class Order
    {
        public int OrderID { get; set; }
        public string Title { get; set; }
        public Customer Customer { get; set; }
        public List<Article> Articles { get; set; } = new List<Article>();
...

Für die Datenabfrage habe ich mir einen kleine Abstraktionsschicht geschrieben:

C#-Code:
    public class LocalDb : IAvService
    {
        private LiteDB.LiteDatabase _db;


        private ILiteCollection<Order> GetOrderCollection
        {
            get { return _db.GetCollection<Order>("orders"); }
        }
        private ILiteCollection<Customer> GetCustomerCollection
        {
            get { return _db.GetCollection<Customer>("customers"); }
        }

        private ILiteCollection<Article> GetArticleCollection
        {
            get { return _db.GetCollection<Article>("articles"); }
        }


        public LocalDb(string dbFile)
        {
            _db = new LiteDatabase(dbFile);
            BsonMapper.Global.Entity<Order>()
                .DbRef(x => x.Customer, "customers");
            BsonMapper.Global.Entity<Order>()
                .DbRef(x => x.Articles, "articles");
            BsonMapper.Global.Entity<Customer>()
                .DbRef(x => x.Orders, "orders");
            BsonMapper.Global.Entity<Article>()
                .DbRef(x => x.Order, "orders");
        }

        public Task<Customer> AddCustomer(Customer customer)
        {
            return Task<Customer>.Run(() =>
            {
                var col = GetCustomerCollection;
                var id  = col.Insert(customer);
                return col.FindById(id);
            });
        }
...

Erstelle ich einen neuen Auftrag mit Artikeln und Kunde löse ich das bisher so.
Da die Objekte (Artikel, Customer....) noch keine ID haben, muss ich sie erst separat in die Datenbank geben.

C#-Code:
            IAvService av = new LocalDb("test.db");

            Order order = new Order
            {
                Title = "Test"
            };


            Article article1 = new Article
            {
                Title = "Arbeitszeit",
                Price = 60,
                Tax = 0.16
            };

            var dbArticle = av.AddArticle(article1).GetAwaiter().GetResult();

            Console.WriteLine($"Artikel ID: {dbArticle.ArticleID}");

            order.Articles.Add(dbArticle);

            order.Customer = av.AddCustomer(new Customer()
            {
                Firstname = "Max",
                Lastname = "Mustermann"
            }).GetAwaiter().GetResult();

            av.AddOrder(order);

Hier wollte ich fragen ob das soweit alles passt, da sich das ja durch mein komplettes Programm ziehen wird.
Was mich noch etwas stört ist bzw. was etwas unschön aussieht, dass ich alles erst Adden muss,
also es nicht direkt hinzufügen kann, wie bei EF: (Oder geht das doch irgendwie damit?)

C#-Code:
Order order = new Order{
   Customer = new Customer{...}
}

Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von JimStark am 20.09.2020 20:51.

20.09.2020 20:40 Beiträge des Benutzers | zu Buddylist hinzufügen
witte
myCSharp.de-Mitglied

Dabei seit: 03.09.2010
Beiträge: 926


witte ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Was soll eigentlich

Code:
1:
.GetAwaiter().GetResult()

bezwecken? Sind diese Addxxx-Methoden wirklich asynchron? Warum verwendest du dann nicht await (mit Task.ConfigureAwait(false))? Das sieht deadlock-verdächtig aus. Implementiere das gleich richtig wenn du es überall einsetzen willst.
20.09.2020 22:08 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.280
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

LiteDB hat kein Async support; das Wrappen in ein Task.Run() ist weit verbreiteter Workaround dafür.
Wenn man es dann aber wieder synchron umsetzt (.GetAwaiter().GetResult()) macht das wenig sinn; dann lieber alles nur Synchron anbieten.

C#-Code:
    public class LocalDb : IAvService
    {
        private LiteDB.LiteDatabase _db;

Von der Umsetzung ist das soweit (grundlegend) korrekt; vom Naming im Sinne der Software Architektur nicht.
Im Endeffekt ist das weder ein Service, noch eine Db - sondern im Prinzip nichts anderes als (eine sehr einfache Variante) des Repository Pattern.


Falls Du Dich inspirieren lassen willst; ich hab zu LiteDB vor ein paar Jahren schon eine Lib geschrieben für ein damaliges Tool.
 SchwabenCode.Data.LiteDBRepository
21.09.2020 09:31 Beiträge des Benutzers | zu Buddylist hinzufügen
JimStark
myCSharp.de-Mitglied

avatar-1005.jpg


Dabei seit: 10.03.2020
Beiträge: 154
Entwicklungsumgebung: Visual Studio 6.0 Enterprise

Themenstarter Thema begonnen von JimStark

JimStark ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von witte:
Sind diese Addxxx-Methoden wirklich asynchron? Warum verwendest du dann nicht await (mit Task.ConfigureAwait(false))?

Nein, ich wollte es im Interface aber als Task definieren, dass ich später evtl. mal eine asynchrone REST-, RPC-Schnittstelle oder ähnliches dazwischen klemmen könnte.
Der Aufruf soll später auch mit await stattfinden, das war nur ein Testaufruf in einer Konsole.

Zitat von Abt:
Im Endeffekt ist das weder ein Service, noch eine Db - sondern im Prinzip nichts anderes als (eine sehr einfache Variante) des Repository Pattern.

Oh man, dieses Pattern vorher zu kennen wäre nützlich gewesen... großes Grinsen
Wen es interessiert, hier habe ich auch ein gutes Beispiel gefunden:  Implementieren von Repository-und Arbeitseinheiten Mustern in einer ASP.NET MVC-Anwendung (9 von 10)

Vielleicht baue ich direkt auf deinen Code auf großes Grinsen

Danke euch beiden!

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von JimStark am 21.09.2020 09:59.

21.09.2020 09:58 Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 14.280
Herkunft: Stuttgart/Stockholm


Abt ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von JimStark:
Der Aufruf soll später auch mit await stattfinden, das war nur ein Testaufruf in einer Konsole.

Dann mach

C#-Code:
public static async Task Main()

in Deiner Konsole.

Geht seit C# 7.1

Technisch gesehen macht der Compiler dann folgendes

C#-Code:
// Wird automatisch erzeugt
public static void Main(string[] args)
{
    Main(args).GetAwaiter().GetResult();
}

// vom Entwickler
private static async Task Main(string[] args)
{
    ... // Main body here
}

Du merkst; wenn die Leute nicht Dein Code vollständig vor Augen haben und Du nichts erklärst, dann kommts zu Verwirrungen ;-)
21.09.2020 10:13 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 2 Monate.
Der letzte Beitrag ist älter als 2 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 23.11.2020 17:21