Cli*_*rce 7 t-sql linq temp-tables
试图解决:
我想我偶然发现了一个解决方案,我想看看它是否是一种解决问题的犹太方式.
(简短摘要)我想对一个记录ID列表进行linq-join,这些记录id不是(完全或至少很容易)在SQL中生成的.这是一个很大的列表,经常超过TDS RPC调用的2100项限制.所以我在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>
Run Code Online (Sandbox Code Playgroud)
打开设计器并关闭它会在那里添加必要的条目,但为了完整起见,我将引用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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后它就变成了在代码中处理一些事情的问题.我通常在哪里:
MyDBDataContext mydb = new MyDBDataContext();
Run Code Online (Sandbox Code Playgroud)
我必须让它与普通的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();
Run Code Online (Sandbox Code Playgroud)
并使用它:
// 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;
Run Code Online (Sandbox Code Playgroud)
有没有人看到这种方法的问题作为在Linq中使用临时表的通用解决方案?
它完美地解决了我的问题,因为现在我可以在Linq中直接加入而不必使用.Contains().
后记:我遇到的一个问题是在表上混合Linq和常规SqlCommands(其中一个是读/写,另一个是另一个)可能是危险的.总是使用SqlCommands在表上插入,然后Linq命令读取它工作正常.显然,Linq缓存结果 - 可能有一种解决方法,但这并不明显.
我认为使用临时表来解决您的问题没有问题。至于混合 SqlCommands 和 LINQ,您对危险因素的看法是完全正确的。使用 DataContext 执行 SQL 语句非常容易,我什至不用担心 SqlCommand:
private string _ConnectionString = "<your connection string>";
public void CreateTempTable()
{
using (MyDBDataContext dc = new MyDBDataContext(_ConnectionString))
{
dc.ExecuteCommand("create table #temptab (recno int primary key not null)");
}
}
public void DropTempTable()
{
using (MyDBDataContext dc = new MyDBDataContext(_ConnectionString))
{
dc.ExecuteCommand("DROP TABLE #TEMPTAB");
}
}
public void YourMethod()
{
CreateTempTable();
using (MyDBDataContext dc = new MyDBDataContext(_ConnectionString))
{
...
... do whatever you want (within reason)
...
}
DropTempTable();
}
Run Code Online (Sandbox Code Playgroud)