Frage

Ich habe ein sehr großes Problem und kann nicht scheinen, sonst jemanden im Internet zu finden, das mein Problem hat. Ich hoffe, dass Stackoverflow kann mir helfen ...

ich eine ASP.NET MVC-Anwendung schreibe, und ich bin das Repository-Konzept mit Linq Verwendung als meine Datenspeicher auf SQL. Alles ist das Arbeiten groß in Bezug auf die Reihen von Ansichten auswählen. Und Trapping sehr grundlegende Einschränkungen Geschäftsregel. Allerdings bin ich mit einem Problem in meinem gespeicherten Prozedur Mappings für Löschungen, Einfügungen und Updates konfrontiert. Lassen Sie mich erklären:

Unsere DBA hat viel Arbeit in setzen die Business-Logik in allen unseren Stored Procedures setzen, damit ich muss darüber an meinem Ende keine Sorge. Sicher, ich grundlegende Validierung zu tun, aber er verwaltet die Datenintegrität und widersprüchliche Datum Einschränkungen, etc ... Das Problem, das ich mit konfrontiert bin, ist, dass alle gespeicherten Prozeduren (und ich meine alle) haben 5 weitere Parameter (6 für Einsätze ), die Informationen zurück zu mir bieten. Die Idee ist, dass, wenn etwas kaputt geht, ich den Benutzer mit den entsprechenden Informationen aus unserer Datenbank veranlassen kann.

Zum Beispiel:

sp_AddCategory(
    @userID INT,
    @categoryName NVARCHAR(100),
    @isActive BIT,
    @errNumber INT OUTPUT,
    @errMessage NVARCHAR(1000) OUTPUT,
    @errDetailLogID INT OUTPUT,
    @sqlErrNumber INT OUTPUT,
    @sqlErrMessage NVARCHAR(1000) OUTPUT,
    @newRowID INT OUTPUT)

Aus der obigen gespeicherten Prozedur, die ersten drei Parameter sind die einzigen Parameter, die verwendet werden, um „zu Erstellen“ die Kategorie Rekord. Die übrigen Parameter werden einfach verwendet, mir zu sagen, was in dem Verfahren passiert ist. Wenn eine Geschäftsregel innerhalb der gespeicherten Prozedur gebrochen ist, so sieht er nicht ‚Raiseerror‘ Keyword SQL verwenden, wenn Geschäftsregeln gebrochen werden. Stattdessen liefert er Informationen über den Fehler zu mir zurück auf die Ausgangsparameter verwenden. Er tut dies für jede einzelne gespeicherte Prozedur in unserer Datenbank auch die Aktualisierungen und Löschungen. Alle ‚Get‘ Anrufe werden mit benutzerdefinierten Ansichten getan. Sie werden alle getestet und die Idee war, meine Arbeit leichter zu machen, da ich die Business-Logik nicht alle der verschiedenen Szenarien zu stoppen hinzufügen müssen, um die Datenqualität zu gewährleisten.

Wie gesagt, ich bin mit LINQ to SQL, und ich bin jetzt mit einem Problem konfrontiert. Das Problem ist, dass mein „Kategorie“ Modellobjekt einfach 4 Eigenschaften hat darauf: CategoryID, Category, Benutzer-ID und IsActive. Als ich den Designer geöffnet, um zu beginnen Kartierung meine Eigenschaften für den Einsatz, erkannte ich, dass es wirklich keine ist (leicht) Weg für mich, für die zusätzlichen Parameter zu berücksichtigen, es sei denn, ich sie zu meinem Model-Objekt hinzuzufügen.

Theoretisch, was ich möchte, ist, dies zu tun:

// note: Repository Methods
public void AddCategory(Category category)
{
    _dbContext.Categories.InsertOnSubmit(category);
}

public void Save()
{
    _dbContext.SubmitChanges();
}

Und dann von meiner CategoryController Klasse würde ich einfach wie folgt vor:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
    var category = new Category();
    try 
    {
        UpdateModel(category); // simple validation here...

        _repository.AddCategory(category);
        _repository.Save(); // should get error here!!

        return RedirectToAction("Index");
    }
    catch
    {
        // manage friendly messages here somehow... (??)
        // ...

        return View(category);
    }
}

Was ist der beste Weg, dies mithilfe von Linq verwalten, um SQL? Ich (persönlich) nicht das Gefühl, dass es Sinn macht, all diese zusätzlichen Eigenschaften für jedes Modell-Objekt hinzugefügt hat ... Zum Beispiel des ‚Get‘ NIEMALS Fehler haben, und ich möchte nicht meine Repository Methoden einen zurückzukehren Objekttyp für Erhalten Sie Anrufe, aber eine andere Art von Objekt für CUD Anrufe annehmen.

Update: Meine Lösung! (1. Dezember 2009)

Hier ist, was ich tat, um mein Problem zu beheben. Ich habe auf alle meine Repositories meiner ‚Save ()‘ Methode befreien. Stattdessen fügte ich eine ‚Update ()‘ Methode zu jedem Repository und tatsächlich die Daten in die Datenbank auf jedem CUD begehen (dh. Erstellen / Aktualisieren / Löschen) -Aufruf.

Ich wusste, dass jede gespeicherte Prozedur die gleichen Parameter hatte, so habe ich eine Klasse, sie zu halten:

public class MySprocArgs 
{
    private readonly string _methodName;
    public int? Number;
    public string Message;
    public int? ErrorLogId;
    public int? SqlErrorNumber;
    public string SqlErrorMessage;
    public int? NewRowId;

    public MySprocArgs(string methodName)
    {
        if (string.IsNullOrEmpty(methodName))
            throw new ArgumentNullException("methodName");

        _methodName = methodName;
    }

    public string MethodName
    {
        get { return _methodName; }
    }

}

Ich habe auch eine MySprocException, die die MySprocArgs in seinem Konstruktor akzeptiert:

public class MySprocException : ApplicationException
{

    private readonly MySprocArgs _args;
    public MySprocException(MySprocArgs args) : base(args.Message)
    {
       _args = args;
    }

    public int? ErrorNumber
    {
        get { return _args.Number; }
    }

    public string ErrorMessage
    {
        get { return _args.Message; }
    }

    public int? ErrorLogId
    {
        get { return _args.ErrorLogId; }
    }

    public int? SqlErrorNumber
    {
        get { return _args.SqlErrorNumber; }
    }

    public string SqlErrorMessage
    {
        get { return _args.SqlErrorMessage; }
    }
}

Jetzt ist hier, wo alles zusammen kommt ... Mit dem Beispiel, das ich mit meiner ersten Anfrage gestartet, hier ist das, was die ‚AddCategory ()‘ Methode aussehen könnte:

public void AddCategory(Category category)
{
   var args = new MySprocArgs("AddCategory");
   var result = _dbContext.AddWidgetSproc(
                    category.CreatedByUserId,
                    category.Name,
                    category.IsActive,
                    ref args.Number, // <-- Notice use of 'args'
                    ref args.Message,
                    ref args.ErrorLogId,
                    ref args.SqlErrorNumber,
                    ref args.SqlErrorMessage,
                    ref args.NewRowId);

   if (result == -1)
      throw new MySprocException(args);
} 

Jetzt von meinem Controller, habe ich einfach wie folgt vor:

[HandleError(ExceptionType = typeof(MySprocException), View = "SprocError")]
public class MyController : Controller
{
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Category category)
    {
        if (!ModelState.IsValid)
        { 
            // manage friendly messages        
            return View(category);
        }

        _repository.AddCategory(category);
        return RedirectToAction("Index");

    } 
}

Der Trick, um die neue MySprocException zu verwalten ist, einfach trap es das Handle Attribut und den Benutzer auf eine Seite umgeleitet, die die MySprocException versteht.

Ich hoffe, das jemand hilft. :)

War es hilfreich?

Lösung

Ich glaube nicht, dass Sie die Ausgangsparameter zu jedem Ihrer LINQ Klassen hinzufügen können, da die Parameter in einer Tabelle bestehen die Datenbank nicht in.

Sie können aber Ausgabeparameter in LINQ in der folgenden Art und Weise behandeln.

Fügen Sie die gespeicherte Prozedur (en) Sie whish auf Ihre .dbml rufen Sie den Designer.

Rufen Sie Ihre gespeicherte Prozedur im Code

 using (YourDataContext context = new YourDataContext())
 {
    Nullable<int> errNumber = null;
    String errMessage = null;
    Nullable<int> errDetailLogID = null;
    Nullable<int> sqlErrNumber = null;
    String sqlErrMessage = null;
    Nullable<int> newRowID = null;
    Nullable<int> userID = 23;
    Nullable<bool> isActive=true;

    context.YourAddStoredProcedure(userID, "New Category", isActive, ref errNumber, ref errMessage, ref errDetailLogID, ref sqlErrNumber, ref sqlErrMessage, ref newRowID);
 }

Andere Tipps

I haven‘versucht, es noch nicht, aber Sie in diesem Artikel sehen kann, wo er über gespeicherte Prozeduren spricht, die Ausgabeparameter zurück.

http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx

Grundsätzlich ziehen die gespeicherte Prozedur in die LINQ to SQL-Designer dann sollte es die Arbeit für Sie tun.

Die dbContext.SubmitChanges(); nur für ENTITY FRAMEWORK.I vorschlagen Speichern, Aktualisieren arbeiten und arbeiten löschen, indem Sie eine einzelne gespeicherte Prozedur oder 3 verschiedene Verfahren.

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