При попытке решить:
Linq. Содержит с большим набором причин Ошибка TDS
Я думаю, что наткнулся на решение, и я хотел бы посмотреть, если это кошерный способ решения проблемы.
(краткое резюме) Я хотел бы объединить linq-join со списком идентификаторов записей, которые (полностью или хотя бы легко) не генерируются в SQL. Это большой список, который часто выходит за пределы 2100 пунктов для вызова TDS RPC. Поэтому то, что я сделал в SQL, бросило их во временную таблицу, а затем присоединилось к этому, когда они мне понадобились.
Так что я сделал то же самое в Linq.
В моем файле MyDB.dbml я добавил:
<Table Name="#temptab" Member="TempTabs">
<Type Name="TempTab">
<Column Name="recno" Type="System.Int32" DbType="Int NOT NULL"
IsPrimaryKey="true" CanBeNull="false" />
</Type>
</Table>
Открытие дизайнера и его закрытие добавило необходимые записи, хотя для полноты приведу цитату из файла 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));
}
}
}
Тогда это просто стало вопросом подтасовок некоторых вещей в коде. Где бы я обычно имел:
MyDBDataContext mydb = new MyDBDataContext();
Мне нужно было заставить его делиться своим соединением с обычным SqlConnection, чтобы я мог использовать это соединение для создания временной таблицы. После этого он кажется вполне пригодным для использования.
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();
И используя его:
// 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;
Кто-нибудь видит проблему с этим подходом в качестве универсального решения для использования временных таблиц в соединениях в Linq?
Это решило мою проблему чудесно, так как теперь я могу сделать прямое объединение в Linq вместо того, чтобы использовать .Contains ().
Постскриптум :
Единственная проблема, которая у меня есть, заключается в том, что смешивание Linq и обычных SqlCommands на столе (где одна читает / пишет, а другая - другая) может быть опасным. Всегда используя SqlCommands для вставки в таблицу, а затем команды Linq для чтения это работает отлично. Очевидно, Linq кеширует результаты - возможно, есть способ обойти это, но это было неочевидно.