Autor Beitrag
Määx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 123



BeitragVerfasst: Fr 15.02.13 13:50 
Hallo zusammen,

ich habe mir eine Datenbankklasse geschrieben, die eigentlich mit LINQ Datensätze auslesen und einfügen soll. Das Auslesen funktioniert auch wunderbar. Leider habe ich bei dem Insert ein Problem mit dem Primärschlüssel: Ich bekomme die folgende Fehlermeldung
"Ein expliziter Wert für die Identitätsspalte kann nicht in der Tabelle eingefügt werden, wenn IDENTITY_INSERT auf OFF festgelegt ist."
Dass dies nicht geht ist kla rund auch korrekt, da die DB diesen ja vergeben soll. Aber wie kann ich dem Insert-Befehl sagen, dass er den Primärshclüssel nicht übergeben soll?
Folgenden Code habe ich jetzt:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
[Table(Name = "Personen")]
public class Person : INotifyPropertyChanged
{
      //[...]
      [Column(Name = "Person_ID", IsPrimaryKey = true)]
        public int person_id
        {
            get { return _person_id; }
            set
            {
                if (_person_id!= value)
                {
                    _person_id= value;
                    OnPropertyChanged("person_id");
                }
            }
        }
       //{...]
}


Und nach dem öffnen der Datenbank (SqlConnection) führe ich dann folgenden Code aus:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
Person p = new Person();
//[...]
DataContext db = new DataContext(sqlCon);
db.GetTable<Person>().InsertOnSubmit( p );
db.SubmitChanges();


Was muss ich LINQ noch mitteilen, damit er alle Daten außer dem Primärschlüssel an die DB sendet und dann p.person_id mit dem neuen Primärschlüssel überschreibt?

Vielen Dank für eure Hilfe.
Määx
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 15.02.13 14:05 
vermutlich mußt du noch IsDbGenerated=true am Columm Attribut setzen.

Wenn du noch in der Frühphase der Entwicklung des Datenmodels bist solltest du überlegen ob du wirklich Linq2Sql verwenden willst. Linq2Sql existiert zwar noch wurde aber mehr oder weniger durch das EntityFramework ersetzt.
Määx Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 123



BeitragVerfasst: Fr 15.02.13 14:25 
ja genau das hat gefehlt!

oh, ich dachte ich bin mit LINQ auf das aktuellste gegangen...
Das Datenbankmodel steht bereits. Für die Kommunikation aus C# habe ich bisher aber kaum was gemacht. Werde mir dann mal das EntityFramework anschauen. Danke für den Tip!!

Viele Grüße
Määx
Määx Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 123



BeitragVerfasst: Fr 15.02.13 15:52 
Hey,

also ich habe mir das EntityFramework jetzt mal angesehen. Das auslesen aus der DB funktionierte wieder perfekt, nur das Einfügen hat wieder einen Fehler verursacht:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
DBEntities context = new DBEntities();
            
Personen p = new Personen();
p.Name = "";
context.Personen.Add(p);
try
{
   scont.SaveChanges();

catch (Exception ex)
{
   MessageBox.Show(ex.Message);
}

Er sagt mir dann, dass ein Fehler beim aktualisieren der Einträge aufgetreten ist. In der Datenbank habe ich für alle Parameter (vom Primärschlüssel abgesehen) den Wert NULL erlaubt.

Zum anderen habe ich noch eine Frage zu LINQ/EntityFramework:
Ich hatte mir jetzt ja meine eigenen Klassen Person, Transaktion usw. geschrieben und diese dann auf die DB gemappt. Das macht das EntityFramework jetzt ja automatisch. Ich hatte jetzt aber neben den DB-Feldern noch weitere Funktionalitäten & Variablen mit in die Klassen eingebaut.
So hatte die Klasse Person z.B. eine List<Transaktion> transaktionen, in der alle Transaktionen abgespeichert waren. Die Klasse Transaktionen war wiederum mit der DB verknüpft und die Tabelle verweist mit einem Fremdschlüssel auf Person.
Beim speichern der Person hätte ich ja immer die Liste durchlaufen müssen und alle Transaktionen einzeln in die DB schieben/updaten müssen.
Bietet hier das Framework einfachere Möglichkeiten dies zu realisieren? Sonst würde ich die automatisch erzeugte Klasse Personen entsprechend an meine bedürfnisse anpassen (für die INotifyPropertyChanged muss ich hier ja eh rumfummeln).

Edit:
achso was mir bei dem EntityFramework noch aufgefallen ist ist, dass ich wenn ich im ProjektA das ganze einbinde und in ProjektB einen Verweis auf ProjektA lege, habe ich die Klasse Personen nicht in ProjektB zur Verfügung. Das ist für mich jedoch erforderlich. Muss man hier noch irgendwelche Einstellungen übernehmen? Ich will in ProjektB nur auf das Obejkt, nie auf die Datenbank zugreifen...

Vielen Dank
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 15.02.13 16:27 
Zitat:
Er sagt mir dann, dass ein Fehler beim aktualisieren der Einträge aufgetreten ist.


Eigentlich ist das System genauer als das. Es sagt nicht nur "geht nich"

Zitat:
Beim speichern der Person hätte ich ja immer die Liste durchlaufen müssen und alle Transaktionen einzeln in die DB schieben/updaten müssen.


Wenn es in der Datenbank eine Beziehung zwischen Person und Transaktionen gibt wird die auch in deinem Model abgebildet. Deine Personen Klasse soltle also auch eine entsprechende Transaktionen Property haben der du Objekte hinzufügen kannst oder über die du Transaktionen Objekte ändern kannst. En simpler Aufruf von SaveChanges wird das dann schon passend auflösen. Da sollte von deiner Seite aus sonst nichts zu tun sein.

Zitat:
achso was mir bei dem EntityFramework noch aufgefallen ist ist, dass ich wenn ich im ProjektA das ganze einbinde und in ProjektB einen Verweis auf ProjektA lege, habe ich die Klasse Personen nicht in ProjektB zur Verfügung. Das ist für mich jedoch erforderlich. Muss man hier noch irgendwelche Einstellungen übernehmen? Ich will in ProjektB nur auf das Obejkt, nie auf die Datenbank zugreifen...


Entityklassen sind Klassen wie jede andere auch da gelten keine besonderen Regeln. Wenn du die irgendwo nicht benutzen kannst solltest du prüfen ob du irgendwas an den Sichtberkeiten der Klassen verbastelt hast.
Määx Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 123



BeitragVerfasst: Fr 15.02.13 18:12 
ok, das mit dem Insert konnte ich zwar noch nicht beheben, ich habe mich jetzt aber wegen der "veralteten" Version von Linq2SQL für das EntityFramework entschieden und nun erstmal sämtliche vom Designer erstellen Klassen dahingehen abgeändert, dass sie mit einer DataBinding versehen werden können.
Jetzt habe ich abr das Problem, dass die Relationen als ICollection dargestellt werden und somit nicht mehr serialisierbar sind. Dies benötige ich jedoch für MSMQ-Messages. Gibt es hier eine möglichkeit das zu ändern oder sollte ich die MEssages auf ein minimum reduzieren und Details dann via SOAP anfordern? Das müsste dann ja eigentlich auch mit komplexeren Objekten möglich sein?

Mit dem Insert-Befehl bastel ich noch ein wenig rum...

Vielen Dank
Määx