Voici les technologies pertinentes que je travaille:Pouvez-vous inclure les modifications linq-to-sql et les mises à jour de l'adaptateur de table de jeu de données ADO.NET dans une seule transaction?
- point de Devart Connect pour Oracle (pour faciliter Linq-à-Sql pour Oracle).
- Datasets ADO.NET fortement typés.
- Une base de données Oracle.
Voici le défi:
- Mon code existant soumet des mises à jour de base de données avec des ensembles de données ADO.NET et adaptateurs de table.
- J'aimerais commencer à convertir ce code en Linq-to-Sql, mais je voudrais le faire au coup par coup pour minimiser le risque de perte de code.
Voilà ma preuve de schéma concept:
Parent Tableau
- Parent.Id
- Parent.Name
Table enfant
- Child.Id
- Child.ParentId
- Child.Name
Voici ma preuve de bloc de code concept:
using System;
using System.Data.Common;
using DevArtTry1.DataSet1TableAdapters;
namespace DevArtTry1
{
class Program
{
static void Main(string[] args)
{
using (DataContext1 dc = new DataContext1())
{
dc.Connection.Open();
using (DbTransaction transaction = dc.Connection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
dc.Transaction = transaction;
Parent parent = new Parent();
parent.Id = 1;
parent.Name = "Parent 1";
dc.Parents.InsertOnSubmit(parent);
dc.SubmitChanges(); // By virtue of the Parent.Id -> Child.ParentId (M:N) foreign key, this statement will impose a write lock on the child table.
DataSet1.CHILDDataTable dt = new DataSet1.CHILDDataTable();
DataSet1.CHILDRow row = dt.NewCHILDRow();
row.ID = 1;
row.PARENTID = 1;
row.NAME = "Child 1";
dt.AddCHILDRow(row);
CHILDTableAdapter cta = new CHILDTableAdapter();
// cta.Transaction = transaction; Not allowed because you can't convert source type 'System.Data.Common.DbTransaction to target type 'System.Data.OracleClient.OracleTransaction.
cta.Update(dt); // The thread will encounter a deadlock here, waiting for a write lock on the Child table.
transaction.Commit();
}
}
Console.WriteLine("Successfully inserted parent and child rows.");
Console.ReadLine();
}
}
}
- Comme les commentaires ci-dessus indiquent , le thread s'arrêtera indéfiniment sur l'appel de mise à jour de l'adaptateur de données enfant car il attendra indéfiniment un verrou en écriture sur la table enfant. [Note de la relation de clé étrangère: Parent.Id -> Child.ParentId (M: N)]
Voici ma question:
- Je veux envelopper tout le bloc de code dans une transaction.
- Puis-je faire ceci? Considérant que:
- Je veux engager une mise à jour sur la table de parent avec SubmitChanges de Linq à Sql méthode ...
- Et je veux engager une mise à jour sur la table des enfants avec un Jeu de données ADO.NET adaptateur de table.
Voici deux notes intéressantes:
- Toute cette choses fonctionne en inverse. C'est-à-dire, si je voulais soumettre des modifications à la table parente avec un adaptateur de données et change à la table enfant avec linq-à-sql ... que fonctionnerait.
J'ai essayé d'attacher explicitement la transaction à l'adaptateur de données, mais le compilateur ne l'autorisera pas car il s'agit d'un type de transaction différent.
CHILDTableAdapter cta = new CHILDTableAdapter(); cta.Transaction = transaction; // Not allowed because you can't convert source type 'System.Data.Common.DbTransaction' to target type 'System.Data.OracleClient.OracleTransaction'. cta.Update(dt); transaction.Commit();