Załóżmy, że mam taką:
ALTER PROCEDURE [dbo].[BookDetail]
@BookID INT OUTPUT
AS
SET NOCOUNT ON;
SELECT
--[BookID]
[Title]
,[TitlelsOrginalNames]
,[EventDate]
,[Description]
,[HostedBy]
,[Country]
,[PublishYears]
FROM Books
WHERE BookID = @BookID
Co powinienem dodać w kontrolerze, modelu i widoku by jej użyć?
W MVC używa się procedur składowanych tak samo jak w WebForm'am, WPF
czy gdziekolwiek indziej, gdyż jest to tylko warstwa prezentacji. Mam
nadzieję, że nie chcesz od razu łączyć warstwy prezentacji i dostępu
do danych.
Co do użycia, to zobacz na blogu Scott Guthrie. Swego czasu popełnił
niezłą serię nt. Linq to SQL
> Co powinienem dodać w kontrolerze, modelu i widoku by jej użyć?
Dokładnie opisane przykłady możesz znaleźć na stronce aspa w dziale
Learn
http://www.asp.net/mvc/learn/
Zobacz sobie filmik Stephena Waltera, akurat w VB pokazuje, ale
wyjaśnia podstawy:
http://www.asp.net/learn/mvc-videos/video-403.aspx
Z nazwaniem MVC ogólnie warstwą prezentacji chyba trochę przesadziłem.
Normalnie wydzielam sobie domain model do osobnego projektu, a potem
łączę go z warstwą prezentacji, w tym wypadku z widokami z MVC poprzez
kontrolery.
Dzięki!
Doszedłem do czegoś takiego:
public IQueryable<Book> Pokaz(int bookID)
{
int ? outputParameter = bookID;
// bookID = 1;
return from bookdetail in db.BookDetail(ref
outputParameter)
select db.BookDetail;
}
na select mam monit:
Error 2 The type of the expression in the select clause is incorrect.
Type inference failed in the call to 'Select'. F:\Documents\Visual
Studio 2008\Projects\book_014\TestBook\Models\BookRepository.cs
Wiesz może jak to obejść? Próbowałem już select
db.BookDetail.AsQueryable(); ale coś nie działa.
Zapomniałem się, że piszmy tutaj o procedurach i wyskrobałem wcześniej
inny post. Pewnie się już rozszedł. Nvm.
Wracając do tematu, troche mnie ta nazwa myli. Przez ten ref
przekazujesz parametr do procedury? To jest on tam zbędny.
Aby wywołać procedurę, która zwróci Ci te dane, powinno to wyglądać
mniej więcej tak:
public IQueryable<Book> Pokaz(int bookID)
{
var result = db.BookDetail(bookID);
//...
}
Teraz co do danych wyjściowych. Wynik otrzymasz w obiekcie, który
nazywa się tak samo, jak Twoja procedura z dodanym na końcu słowem
Result. W tym wypadku będzie to BookDetailResult wsadzona jeszcze w
obiekt ISingleResult. Aby zwrócić to coś jako Book z metody, trzeba to
zmapować. Przykładowo:
public IQueryable<Book> Pokaz(int bookID)
{
var result = db.BookDetail(bookID);
Book b;
foreach(var i in result){
b=new Book(){
bookID=i.bookID //i reszte
};
}
return result.asIQueryable();
}
Zakładam, że ta procedura zwraca tylko jeden rekord, więc ten foreach
jest zbędny, ale to tylko przykład poglądowy. Podobnie ten IQueryable
jako typ zwracany. Ja bym to zwrócił po prostu jako jeden obiekt.
Kod obecnie:
public IEnumerable<Book> Pokaz(int BookID)
{
var result = db.BookDetail(BookID);
Book b;
foreach (var i in result)
{
b = new Book()
{
Title = i.Title,
TitlelsOrginalNames = i.TitlelsOrginalNames,
EventDate = i.EventDate,
Description = i.Description,
HostedBy = i.HostedBy,
PublishYears = i.PublishYears
};
return result.AsEnumerable();
}
}
Teraz kompilator sypie inne błędy:
Error 1 The best overloaded method match for
'NerdBook.Models.NerdBookDataContext.BookDetail(ref int?)' has some
invalid arguments F:\Documents\Visual Studio 2008\Projects
\book_014\NerdBook\Models\BookRepository.cs 26 30 NerdBook
Error 4 Metadata file 'F:\Documents\Visual Studio 2008\Projects
\book_014\NerdBook\bin\NerdBook.dll' could not be found NerdBook.Tests
Error 3 Cannot implicitly convert type
'System.Collections.Generic.IEnumerable<NerdBook.Models.BookDetailResult>'
to 'System.Collections.Generic.IEnumerable<NerdBook.Models.Book>'. An
explicit conversion exists (are you missing a cast?) F:\Documents
\Visual Studio 2008\Projects\book_014\NerdBook\Models
\BookRepository.cs 39 28 NerdBook
Error 2 Argument '1': cannot convert from 'int' to 'ref int?' F:
\Documents\Visual Studio 2008\Projects\book_014\NerdBook\Models
\BookRepository.cs 26 44 NerdBook
Rezultatu nie mogę zwrócić bo w procedurze nie ma SELECT * a selectuję
wybrane wartości tabeli (nie wszystkie), nie wiem jak to obejść.
Dodatkowo var result potrzebuje referencje do przepisania w sumie nie
mam pojęcia co tam nie gra.
Odpowiadając poprzednio nie spojrzałem do pierwszego Twojego postu.
Jeżeli rozmawiamy o tej procedurze:
ALTER PROCEDURE [dbo].[BookDetail]
@BookID INT OUTPUT
AS
SET NOCOUNT ON;
SELECT
--[BookID]
[Title]
,[TitlelsOrginalNames]
,[EventDate]
,[Description]
,[HostedBy]
,[Country]
,[PublishYears]
FROM Books
WHERE BookID = @BookID
to moim zdaniem, to słówko output jest zbyteczne. Wystarczy
odkomentować pierwszą linijkę z selecta i później odpowiednio "dobrać"
się do zwróconego Id. Zaznaczyć również tutaj muszę, że w tym wypadku,
jeżeli chcesz również przez ten parametr przekazać nr id dotyczące
odpowiedniej książki, której info chcesz pobrać ( WHERE BookID =
@BookID ), to tak nie przejdzie, chyba że ja czegoś nie wiem. IMO
drugi parametr by trzeba dodać. Jednakże, jeżeli ta procedura
wyglądałaby tak:
ALTER PROCEDURE [dbo].[BookDetail]
@BookID INT,
@BookID INT OUTPUT
czyli w pierwszym parametrze przekazujesz id książki by pobrać jej
dane, to nielogiczne jest później ten id zwracać z tej procedury,
skoro już go masz w przekazanej zmiennej. Wydaje mi się, że po prostu
nie zrozumiałeś, do czego się stosuje słówko output.
Jeżeli z tej procki usuniesz to słowo, to kod, który podałem w
poprzednim moim poście powinien zadziałać poprawnie.
Co do słówka output, zobacz taki z dupy wzięty przykład:
create procedure TestProc(
@result int output
)
as
begin
set @result = 2+2
end
go
declare @res int
exec TestProc @res output
select @res
Na tym można prześledzić, jak to działa.
Z poziomu L2S można takiej procki użyć następująco:
public void GetTheSum()
{
int? result=null;
int a;
a=MyDataContext.TestProc(ref result);
}
Teraz w result masz ten wynik.
Dzięki :).