Próbując rozwiązać:Tabele tymczasowe w Linq - Czy ktoś ma z tym problem?
Linq .Contains with large set causes TDS error
myślę, że natknął się na rozwiązanie, i chciałbym, aby zobaczyć, czy jest to koszerny sposób zbliża się do problemu.
(krótkie podsumowanie) Chciałbym dołączyć do linq-join z listą identyfikatorów rekordów, które nie są (w całości lub przynajmniej łatwo) generowane w SQL. Jest to duża lista i często przekracza limit 2100 pozycji dla wywołania RPC TDS. Więc to, co bym zrobił w SQL, rzuciłoby je w tymczasowy stół, a potem połączyłem się z nim, gdy ich potrzebowałem.
Zrobiłem to samo w Linq.
W moim pliku MyDB.dbml I dodaje:
<Table Name="#temptab" Member="TempTabs">
<Type Name="TempTab">
<Column Name="recno" Type="System.Int32" DbType="Int NOT NULL"
IsPrimaryKey="true" CanBeNull="false" />
</Type>
</Table>
Otwieranie i zamykanie projektant dodał niezbędne wpisy tam, chociaż pod względem kompletności, będę cytować z pliku MyDB.desginer.cs:
[Table(Name="#temptab")]
public partial class TempTab : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _recno;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnrecnoChanging(int value);
partial void OnrecnoChanged();
#endregion
public TempTab()
{
OnCreated();
}
[Column(Storage="_recno", DbType="Int NOT NULL", IsPrimaryKey=true)]
public int recno
{
get
{
return this._recno;
}
set
{
if ((this._recno != value))
{
this.OnrecnoChanging(value);
this.SendPropertyChanging();
this._recno = value;
this.SendPropertyChanged("recno");
this.OnrecnoChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Potem stało się po prostu żonglowanie niektórymi rzeczami w kodzie. Gdzie bym normalnie mieli:
MyDBDataContext mydb = new MyDBDataContext();
musiałem zmusić go do udostępniania połączenia z normalnym SqlConnection, abym mógł korzystać z połączenia, aby utworzyć tabelę tymczasową. Po tym wydaje się całkiem użyteczny.
string connstring = "Data Source.... etc..";
SqlConnection conn = new SqlConnection(connstring);
conn.Open();
SqlCommand cmd = new SqlCommand("create table #temptab " +
"(recno int primary key not null)", conn);
cmd.ExecuteNonQuery();
MyDBDataContext mydb = new MyDBDataContext(conn);
// Now insert some records (1 shown for example)
TempTab tt = new TempTab();
tt.recno = 1;
mydb.TempTabs.InsertOnSubmit(tt);
mydb.SubmitChanges();
i używając go:
// Through normal SqlCommands, etc...
cmd = new SqlCommand("select top 1 * from #temptab", conn);
Object o = cmd.ExecuteScalar();
// Or through Linq
var t = from tx in mydb.TempTabs
from v in mydb.v_BigTables
where tx.recno == v.recno
select tx;
Czy ktoś widzi problem z tym podejściem, jako rozwiązanie dla ogólnego przeznaczenia przy użyciu tabel tymczasowych w przyłącza się Linq?
To rozwiązało mój problem cudownie, ponieważ teraz mogę zrobić proste dołączenie do Linq zamiast używać .Contains().
Postscript: Jeden problem mam jest to, że mieszanie Linq i regularne SqlCommands na stole (gdzie jedna jest odczytu/zapisu i tak jest inny) może być niebezpieczne. Zawsze używa SqlCommands do wstawienia do tabeli, a następnie polecenia Linq do odczytu działają dobrze. Wygląda na to, że Linq buforuje wyniki - prawdopodobnie jest to możliwe, ale nie było to oczywiste.
Szczerze mówiąc, nie testowałem rozwiązania, które dostarczyłem, używając tabel tymczasowych. Biorąc to pod uwagę, rozwiązanie na pewno zadziała przy użyciu "stałych" tabel. Ponadto powodem, dla którego używam metody DataContext.ExecuteCommand() jest to, że instrukcja SQL nie jest w ogóle obsługiwana przez silnik LINQ ... to, co wysyłasz, jest uruchamiane. –