Frage

Ich habe mit Linq begann in einem (Bit DDD mögen) System SQL, die (übermäßig vereinfacht) wie folgt aussieht:

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;
    }
}

Nun habe ich ein Problem. Wenn ich versuche, SomeEntityRepository wie diese zu nutzen

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);
    }
 }

alles funktioniert gut, bis das Programm zum letzten Console.WriteLine bekommt, weil es eine ObjectDisposedException wirft, weil das Datacontext nicht mehr existiert.

ich sehe das eigentliche Problem, aber wie das ich lösen? Ich denke, es gibt mehrere Lösungen, aber keiner von denen, die ich von bisher gedacht hätte in meiner Situation gut sein.

  • Rau aus den Repository-Mustern entfernt und ein neues Datacontext für jeden Atom Teil der Arbeit verwenden.
    • Ich würde wirklich nicht will, dies zu tun. Ein Grund ist, dass ich will nicht die Anwendungen bewusst sein, das Repository zu sein. Ein weiterer ist, dass ich nicht glaube, linq2sql Sachen COM sichtbar zu machen wäre gut.
    • Außerdem glaube ich, dass context.SubmitChanges() tun wahrscheinlich viel mehr begehen würde, als ich wollte.
  • Dataload Festlegen zugehörige Elemente zu holen.
    • Wie ich meine Business-Logik-Schicht möchte mit einigen Einheiten in einigen Fällen nur antworten, ich weiß nicht, welche Unter Eigenschaften, die sie verwenden müssen.
  • Deaktivieren verzögertes Laden / verzögert Laden für alle Eigenschaften.
    • Keine Option, denn es gibt durchaus ein paar Tische, und sie sind stark verbunden. Dies könnte eine Menge unnötiger Verkehr und Datenbanklast führen.
  • Einige Post im Internet sagte, dass .Single mit () helfen soll.
    • Offenbar hat es nicht ...

Gibt es eine Möglichkeit, dieses Elend zu lösen?

BTW: Wir beschließen, Linq t0 SQL zu verwenden, da es eine relativ leichte ORM-Lösung ist und im Lieferumfang von .NET Framework und Visual Studio. Wenn .NET Entity Framework paßt besser in diesem Muster würde, kann es eine Option zu wechseln, um es sein. (Wir sind nicht so weit in der Durchführung, noch nicht.)

War es hilfreich?

Lösung

Rick Strahl hat einen schönen Artikel über Datacontext-Lifecycle-Management hier: http: / /www.west-wind.com/weblog/posts/246222.aspx .

Grundsätzlich ist der atomare Aktion Ansatz ist schön in der Theorie, aber Sie gehen Ihre Datacontext müssen um halten zu können, Änderungen verfolgen (und Kinder zu holen) in Ihren Datenobjekten.

Siehe auch: Mehrere / Instanz von Linq to SQL Datacontext und LINQ to SQL - wo lebt Ihr Datacontext ? .

Andere Tipps

Sie müssen entweder:

Lassen Sie

1), um den Kontext offen, weil Sie noch nicht vollständig entschieden, welche Daten noch verwendet werden (auch bekannt als Lazy Loading).

oder 2) mehr Daten über die Anfangslast ziehen, wenn Sie wissen, dass Sie, dass andere Eigenschaft benötigen.

Erläuterungen des letzteren: hier

Ich bin mir nicht sicher, dass Sie Repository verlassen, wenn Sie mit atomaren Einheiten der Arbeit gehen. Ich benutze beide, obwohl ich zu werfen die Parallelität Kontrollen zulassen, da sie in Schichten nicht klappt sowieso (ohne einen Zeitstempel oder eine andere erforderliche Konvention). Was ich am Ende mit ist ein Repository, das ein Datacontext verwendet und wirft es weg, wenn es fertig ist.

Dies ist Teil eines nicht verwandten Silverlight Beispiels, aber die ersten drei Teile zeigen, wie ich bin ein Repository-Muster mit einem Wegwerf-LINQ to SQL-Kontext verwenden, FWIW: http://www.dimebrain.com/2008/09/linq-wcf-silver.html

  

Festlegen Dataload zu Elementen holen. Als ich meine Business-Logik-Schicht möchte mit einigen Einheiten in einigen Fällen nur antworten, ich weiß nicht, welche Unter Eigenschaften, die sie verwenden müssen.

Wenn der Anrufer die Kopplung gewährt wird notwendig, die .Relation Eigenschaft zu verwenden, dann auch der Anrufer kann die Dataload angeben.

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;

Das ist, was ich tue, und bisher wirklich gut es funktioniert.

1) Stellen Sie die Datacontext eine Membervariable in Ihrem Repository. Ja, das bedeutet, dass Sie Repository sind, soll jetzt IDisposable implementieren und nicht offen gelassen werden ... vielleicht etwas, was Sie tun, um zu vermeiden wollen, aber ich habe es nicht ungünstig erwiesen.

2) Fügen Sie einige Methoden, um Ihr Repository wie folgt aus:

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

Dann Anrufer sieht wie folgt aus:

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

Sie müssen nur sicherstellen, dass, wenn das Repository die DB trifft, ist es die Daten-Ladeoptionen in diesen Hilfsmethoden angegeben verwendet ... in meinem Fall „DLO“ als Mitglied variabel gehalten wird, und legen Sie dann direkt vor dem Schlagen die db.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top