Avatar billede hlt Juniormester
10. maj 2019 - 18:21 Der er 18 kommentarer og
1 løsning

Extended Class i C#

Hej,
Jeg sidder med et problem med omskrivning af noget PHP kode til C#. Jeg har fået forklaret af en ven, at man i PHP kan extende en klasse som så arver alle metoder fra denne klasse. I koden er der mange forskellige objekter som alle har en insert, update og en delete metode. De 3 metoder vil vi gerne have samlet i en klasse, som så står for SQL kald for alle typer objekter. Men eftersom database klassen ikke kender objekterne og hvor mange variabler hver enkelt objekt har, så skulle man kunne extende database klassen, som derved så får kendskab til det enkelte object. Jeg ved ikke helt om det kan lade sig gøre, og i så fald, er det god programmeringskik at gøre. Det vil være nemmere, kun at have en klasse, men problemet er at database klasse ikke kender det objekt man prøver at gemme.
Giver det mening det jeg skriver?
På forhånd tak
Avatar billede arne_v Ekspert
10. maj 2019 - 18:51 #1
Man kan godt extende en klasse i C#.

Og man kan godt finde alle properties dynamisk i C#.

Men men men.

Jeg ville ikke putte data og funktionaliteten til at gemme data i samme klasse.

Og der er masser af ORM frameworks til .NET hvor man slet ikke skal skrive database tilgangskoden selv. Man giver bare sin data klasse til et ORM framework der saa goer det der skal goeres.
Avatar billede arne_v Ekspert
10. maj 2019 - 18:54 #2
Proev f.eks. at laese afsnit 4, 5 og 6 her:

http://www.vajhoej.dk/arne/articles/dotnetdb.html
Avatar billede hlt Juniormester
10. maj 2019 - 19:44 #3
Jeg synes ikke det er så nemt at læse/forstå. Og jeg ved ikke om det er den vej jeg skal gå. Jeg er faktisk lidt i tvivl om jeg hellere vil have det på den gamle måde. Der er godt nok lidt mere vedligehold, men jeg synes det er nemmere at overskue. Jeg tænkte bare at der var en lille hurtig løsning. Det er sikkert nemt, når først det er sat op. Men jeg er ikke sikker på at jeg nogensinde FÅR det sat op. Og hvad hvis man ikke vil opdatere alt fra sit object, vil man så ikke overskrive de felter i DB med tomt data?
Avatar billede arne_v Ekspert
10. maj 2019 - 20:45 #4
Du kan godt lave en basis klasse som itererer over properties og gemmer i database.

Hvis du kun vil opdatere det som er aendret er du noedt til enten at sammenligne med original data eller tracke hvilke properties der er aendret.
Avatar billede hlt Juniormester
11. maj 2019 - 01:45 #5
Jeg tror det bliver for omstændigt. Jeg kom jo til at tænke på at de forskellige objecter indeholder mere end det der skal opdateres. Tror det bliver for besværligt at holde styr på, i stedet for at lave de funktioner til insert og update på den helt gamle facon :-) Det bliver sådan indtil videre. Men hvordan skulle man i så fald lave en klasse der itererer over et object, når det helst skulle være en klasse som alle objecter kan gemmes/opdaters fra? Meningen var jo at uanset hvilket object man ville gemme/opdatere, skulle det være samme funktion som stod for den. Man skal selvfølgelig bygges sin SQL op, men hvordan får jeg gået alle properties igennem, når jeg ikke ved hvilket object der skal gemmes. Jeg er jo vant til at man f.eks sender et kunder object med som parameter når man kalder funktionen til databasekaldet.
Avatar billede arne_v Ekspert
11. maj 2019 - 03:43 #6
Eksempel:


using System;
using System.Linq;

namespace E
{
    public abstract class Saver
    {
        private static string Q(object v)
        {
            return (v is string) ? ("'" + v + "'") : v.ToString();
        }
        public void Save()
        {
            string clznam = this.GetType().Name;
            string flist = string.Join(",", this.GetType().GetProperties().Select(pi => pi.Name));
            string vlist = string.Join(",", this.GetType().GetProperties().Select(pi => pi.GetValue(this, null)).Select(v => Q(v)));
            string sql = string.Format("INSERT INTO {0}({1}) VALUES({2});", clznam, flist, vlist);
            Console.WriteLine(sql);
        }
    }
    public class X : Saver
    {
        public int A { get; set; }
        public string B { get; set; }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            X o = new X { A = 123, B = "ABC" };
            o.Save();
            Console.ReadKey();
        }
    }
}


Output:

INSERT INTO X(A,B) VALUES(123,'ABC');
Avatar billede arne_v Ekspert
11. maj 2019 - 03:54 #7
Hvis der er nogen som du vil undgaa:


using System;
using System.Linq;

namespace E
{
    public class IgnoreAttribute : Attribute
    {
    }
    public abstract class SmartSaver
    {
        private static string Q(object v)
        {
            return (v is string) ? ("'" + v + "'") : v.ToString();
        }
        public void Save()
        {
            string clznam = this.GetType().Name;
            string flist = string.Join(",", this.GetType().GetProperties().Where(pi => pi.GetCustomAttributes(typeof(IgnoreAttribute), true).Length == 0).Select(pi => pi.Name));
            string vlist = string.Join(",", this.GetType().GetProperties().Where(pi => pi.GetCustomAttributes(typeof(IgnoreAttribute), true).Length == 0).Select(pi => pi.GetValue(this, null)).Select(v => Q(v)));
            string sql = string.Format("INSERT INTO {0}({1}) VALUES({2});", clznam, flist, vlist);
            Console.WriteLine(sql);
        }
    }
    public class X : SmartSaver
    {
        public int A { get; set; }
        public string B { get; set; }
        [Ignore] public string C { get; set; }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            X o = new X { A = 123, B = "ABC", C = "nothing" };
            o.Save();
            Console.ReadKey();
        }
    }
}
Avatar billede hlt Juniormester
13. maj 2019 - 10:34 #8
Tak for koden :-) Beklager det sene svar. Det ser rigtig fint ud. Tror måske jeg vil give det et forsøg. Men er det rigtigt forstået, at når jeg f.eks har et object, som jeg gerne vil gemme, så er jeg nødt til at gemme alle data i objectets properties? Eller er det det kode du har lavet til at ignorere?

Det er et stykke tid siden jeg har brugt eksperten. Er man holdt op med at give points?
Avatar billede hlt Juniormester
13. maj 2019 - 11:06 #9
Har så lige et andet problem. Jeg får en fejl med denne Select(pi => pi.Name)
'PropertyInfo[]' does not contain a definition for 'Select' and no accessible extension method 'Select' accepting a first argument of type 'PropertyInfo[]' could be found (are you missing a using directive or an assembly reference?)

Jeg har prøvet at tilføje en reference til system.data.linq. Men det hjælper ikke.
Avatar billede arne_v Ekspert
13. maj 2019 - 14:53 #10
Det er normalt i C# at man har properties til alle sine data.

Men du kan godt iterere over felter ogsaa.
Avatar billede arne_v Ekspert
13. maj 2019 - 14:54 #11
'PropertyInfo[]' does not contain a definition for 'Select'

lyder som der mangler en:

using System.Linq;

i toppen.
Avatar billede hlt Juniormester
13. maj 2019 - 15:45 #12
Jeg har ikke en system.linq. Den finder jeg i system.data.linq. Så har jeg læst at man skal have system.core. Men den kan jeg ikke få lov til at lave en reference til.
Avatar billede arne_v Ekspert
13. maj 2019 - 15:58 #13
using System.Linq;

i program koden for at importere namespacet.

Det namespace ligger i System.Core.dll assembly, men den behøver du ikke sætte eksplicit ref til.
Avatar billede hlt Juniormester
13. maj 2019 - 18:12 #14
Jeps :-) Men når jeg skriver det, får jeg følgende fejl:
The type or namespace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly reference?)


Det er da lidt underligt ??
Avatar billede arne_v Ekspert
13. maj 2019 - 19:13 #15
Ja.

Hvilken version af .NET/C#/Visual Studio bruger du?
Avatar billede hlt Juniormester
13. maj 2019 - 22:53 #16
Jeg har lige ændret den til version 4.6.1. Den stod til 4.0. Men det ændrede ikke noget. Jeg bruger visual studio express 2017.
Avatar billede arne_v Ekspert
14. maj 2019 - 01:02 #17
Naar du til hoejre i "Solution Explorer" ekspanderer "References" er Systen.Core saa ikke der?
Avatar billede hlt Juniormester
14. maj 2019 - 14:44 #18
Det er et website. Men når jeg åbner websites property page, kan jeg under referencer kun se, dem jeg allerede har importeret. Der er hverken system.core eller system.linq. Der er en system.data.linq, men den duer jo så ikke. Jeg har også lige hentet den nyeste version (2019) af Visual Studio. Jeg kan altså ikke se det nogen steder. Men når jeg går ind og tilføjer en reference og her vælger system.core, får jeg at vide at der allerede er en reference til system.core. Det er da lidt underligt. Hvor kan jeg se det? De andre referencer som jeg kan se i web.config filen, dem kan jeg godt se er valgt.
Avatar billede hlt Juniormester
07. juni 2019 - 11:37 #19
Hej igen,
Lige en hurtig kommentar til dette problem. Det viser sig, at når koden ligger i en class fil i mappen app_code, så kan man ikke bruge using system.linq. Men så snart man flytter den ud i roden, forsvinder fejlen. Lidt underlig fejl. Men det fik mig da sporet lidt ind på en anden løsning. Den er måske ikke helt så elegant som din, men dog noget der virker :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester