Question

J'ai commencé à utiliser Linq en SQL dans un système (similaire à DDD) qui ressemble (trop simplifié) à ceci:

public class SomeEntity // Imagine this is a fully mapped linq2sql class.
{
    public Guid SomeEntityId { get; set; }
    public AnotherEntity Relation { get; set; }
}

public class AnotherEntity // Imagine this is a fully mapped linq2sql class.
{
    public Guid AnotherEntityId { get; set; }
}

public interface IRepository<TId, TEntity>
{
    Entity Get(TId id);
}

public class SomeEntityRepository : IRepository<Guid, SomeEntity>
{
    public SomeEntity Get(Guid id)
    {
        SomeEntity someEntity = null;
        using (DataContext context = new DataContext())
        {
            someEntity = (
                from e in context.SomeEntity
                where e.SomeEntityId == id
                select e).SingleOrDefault<SomeEntity>();
        }

        return someEntity;
    }
}

Maintenant, j'ai un problème. Lorsque j'essaie d'utiliser SomeEntityRepository comme ceci

public static class Program
{
    public static void Main(string[] args)
    {
        IRepository<Guid, SomeEntity> someEntityRepository = new SomeEntityRepository();
        SomeEntity someEntity = someEntityRepository.Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));
        Console.WriteLine(someEntity.SomeEntityId);
        Console.WriteLine(someEntity.Relation.AnotherEntityId);
    }
 }

Tout fonctionne bien jusqu'à ce que le programme atteigne la dernière WriteLine, car il génère une ObjectDisposedException , car le DataContext n'existe plus.

Je vois le problème, mais comment résoudre ce problème? Je suppose qu’il existe plusieurs solutions, mais aucune de celles auxquelles j’avais pensé jusqu’à présent ne serait bonne dans ma situation.

  • Éloignez-vous du modèle de référentiel et utilisez un nouveau DataContext pour chaque partie atomique du travail.
    • Je ne voudrais vraiment pas faire cela. Une raison est que je ne veux pas être les applications à connaître le référentiel. Une autre est que je ne pense pas que rendre visible le truc linq2sql COM serait bien.
    • De plus, je pense que faire context.SubmitChanges () engagerait probablement beaucoup plus que ce que j'avais l'intention de faire.
  • Spécification de DataLoadOptions pour extraire les éléments associés.
    • Comme je souhaite que ma couche logique métier réponde simplement avec certaines entités dans certains cas, je ne sais pas quelles sous-propriétés elles doivent utiliser.
  • Désactiver le chargement différé / différé pour toutes les propriétés.
    • Ce n'est pas une option, car il y a pas mal de tables et elles sont fortement liées. Cela pourrait entraîner beaucoup de trafic inutile et de charge de base de données.
  • Certaines publications sur Internet ont déclaré que l'utilisation de .Single () devrait aider.
    • Apparemment, ce n'est pas ...

Y at-il un moyen de résoudre cette misère?

BTW: Nous avons décidé d’utiliser Linq t0 SQL car c’est une solution ORM relativement légère, incluse dans le framework .NET et Visual Studio. Si le .NET Entity Framework s’intègre mieux dans ce modèle, vous pourrez peut-être y basculer. (Nous ne sommes pas encore si loin dans la mise en œuvre.)

Était-ce utile?

La solution

Rick Strahl a rédigé un article intéressant sur la gestion du cycle de vie de DataContext: http: / /www.west-wind.com/weblog/posts/246222.aspx .

En principe, l'approche par action atomique est intéressante en théorie, mais vous devrez conserver votre DataContext pour pouvoir suivre les modifications (et récupérer les enfants) dans vos objets de données.

Voir aussi: instance unique / multiple de Linq vers SQL DataContext et LINQ to SQL: où réside votre DataContext? .

Autres conseils

Je ne suis pas sûr que vous deviez abandonner Repository si vous utilisez des unités de travail atomiques. J'utilise les deux, bien que j'avoue avoir jeté les contrôles d'optimisation des accès simultanés, car ils ne fonctionnent de toute façon pas dans les couches (sans utiliser un horodatage ou une autre convention requise). Je me retrouve avec un référentiel qui utilise un DataContext et le jette à la fin.

Cela fait partie d'un exemple Silverlight non associé, mais les trois premières parties montrent comment j'utilise un modèle de référentiel avec un contexte LINQ to SQL à jeter, FWIW: http://www.dimebrain.com/2008/09/linq-wcf-silver.html

  

Spécification de DataLoadOptions pour récupérer des éléments associés. Comme je veux que ma couche logique métier réponde simplement avec certaines entités dans certains cas, je ne sais pas quelles sous-propriétés elles doivent utiliser.

Si l'appelant obtient le couplage nécessaire pour utiliser la propriété .Relation, il peut également spécifier l'option DataLoadOptions.

DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Entity>(e => e.Relation);
SomeEntity someEntity = someEntityRepository
  .Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"),
  loadOptions);

//

using (DataContext context = new DataContext())
{
  context.LoadOptions = loadOptions;

C’est ce que je fais et jusqu’à présent, cela a très bien fonctionné.

1) Faites du DataContext une variable membre dans votre référentiel. Oui, cela signifie que votre référentiel doit maintenant implémenter IDisposable et ne pas être laissé ouvert ... peut-être quelque chose que vous voulez éviter, mais je ne l'ai pas trouvé incommodant.

2) Ajoutez des méthodes à votre référentiel comme ceci:

public SomeEntityRepository WithSomethingElseTheCallerMightNeed()
{
 dlo.LoadWith<SomeEntity>(se => se.RelatedEntities);
 return this; //so you can do method chaining
}

Ensuite, votre correspondant ressemble à ceci:

SomeEntity someEntity = someEntityRepository.WithSomethingElseTheCallerMightNeed().Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));

Vous devez simplement vous assurer que lorsque votre référentiel atteint la base de données, il utilise les options de chargement de données spécifiées dans ces méthodes d'assistance ... dans mon cas, "dlo". est conservé en tant que variable membre, puis défini juste avant de frapper la base de données.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top