When trying to solve:
A large set of Linq.Contains causes a TDS error
I think I came across a solution, and I would like to see if this is a kosher way of approaching the problem.
(brief summary) I would like to linq-join against a list of record identifiers that (completely or at least easily) are not generated in SQL. This is a long list and often breaks the limit of 2100 points for calling TDS RPC. So what I would do in SQL, drop them into the temp table, and then join this when I needed it.
So, I did the same in Linq.
In my MyDB.dbml file, I added:
<Table Name="#temptab" Member="TempTabs"> <Type Name="TempTab"> <Column Name="recno" Type="System.Int32" DbType="Int NOT NULL" IsPrimaryKey="true" CanBeNull="false" /> </Type> </Table>
Opening the constructor and closing it added the necessary entries there, although for completeness I will quote from the file 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)); } } }
Then it just became the subject of juggling with some things in the code. Where I usually had:
MyDBDataContext mydb = new MyDBDataContext();
I had to get him to share his connection with a regular SqlConnection so that I could use the connection to create a temporary table. After that, it seems quite usable.
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();
And using it:
// 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;
Does anyone see a problem with this approach as a one-stop solution for using temporary tables in joins in Linq?
He solved my problem wonderfully, since now I can make a direct connection in Linq instead of using .Contains ().
Postscript : The only problem I ran into is that mixing Linq and regular SqlCommands in a table (where you read / write, as well as others) can be dangerous. Always using SqlCommands to insert into a table and then Linq commands to read, this works great. Linq seems to cache the results - perhaps around, but that was not obvious.