WPF LINQ to SQL类自定义
本文关键字:自定义 SQL to LINQ WPF | 更新日期: 2023-09-27 18:29:38
我正在使用Visual Studio Express 2013和SQL Server Express 2014,编写一个使用LINQ to SQL访问数据的WPF应用程序。我的意图是完整的CRUD功能,使用映射到observableCollections的各种UI元素。到目前为止,一切都很好,但我只是使用映射到数据网格的各个表。我想用其中两个表的左联接结果显示一个数据网格,所以在dbml布局中,我创建了一个新表,并使用了一个存储过程作为数据源IDE生成的代码,如下所示:
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.ListAllDocuments")]
public partial class TrackDocument : INotifyPropertyChanging, INotifyPropertyChanged
{ // innards removed for readability }
当我运行此程序时,我会得到一个未处理的异常"无效的对象名称'dbo.ListAllDocuments'"…这是带有Left Join语句的存储过程。如何将查询语言添加到我为表示这些数据而构建的类中?这是一个带有构造函数的可观察类,我用单个表案例对其进行了建模,以最终绑定到UI:
class ObservableTrackDocument : ObservableCollection<TrackDocument>
{
public ObservableTrackDocument(DocControlClassesDataContext dataDc)
{
foreach (TrackDocument tDoc in dataDc.TrackDocuments)
{
this.Add(tDoc);
}
}
}
但是,由于存储过程不能用作源,因此没有为表填充数据上下文。我突然想到,我需要在这里的构造函数中添加LINQ查询,然后执行foreach循环来填充observableCollection:类似这样的东西:
class ObservableTrackDocument : ObservableCollection<TrackDocument>
{
public ObservableTrackDocument(DocControlClassesDataContext dataDc)
{
var query = from f in dataDc.FilesTransmitteds
from r in dataDc.FilesReturneds
.Where(x => f.DocumentNumber == x.DocumentNumber && f.REV == x.REV)
.DefaultIfEmpty()
select new { (list of fields) };
foreach (TrackDocument tDoc in query)
{
this.Add(tDoc);
}
}
}
但这也不起作用(我保留了对dbml布局中TrackDocument类属性列表的存储过程的"Source"引用,这是原始异常的原因)。由于某些原因,编译器无法协调将查询项强制转换为TrackDocument类。
我是否需要重写TrackDocument类中的一个IDE生成的方法来执行在普通单表情况下会导致TrackDocuemnts集合的查询?如果是,你能给我一个如何覆盖的例子吗?类代码在一个自动生成的文件中,所以我知道我不能在那里手动添加东西。
我希望这是清楚的。我对描述这些事情的语言感到困惑。
谢谢,Paul
Paul,
请尝试使用视图而不是存储过程。这将为您提供Linq的类似表格的功能。
如果必须使用存储过程,即返回数据集,则需要为存储过程的返回类型创建一个实体。在DBML设计器中单击存储过程时,检查您的属性是否为"Return Type"(这是将接收SPROC返回的数据的类/表)。
例如,如果您的存储过程是:
CREATE PROCEDURE sp_get_ObservableTrackDocuments
@documentNumber int
AS
BEGIN
SELECT A,B,C
FROM FilesTransmitted, FilesReturned
WHERE DocumentNumber = @documentNumber
END
您可以创建与视图相同的上下文:
CREATE VIEW vw_ObservableTrackDocument
AS
BEGIN
SELECT A,B,C
FROM FilesTransmitted, FilesReturned
END
该视图可以从服务器资源管理器拖放到dbml,并将作为表进行操作。通过这种方式,您可以使用以下代码进行查询:
var otd = vw_ObservableTrackDocuments.Where(x => x.DocumentNumber = "123").ToList();
这将按DocumentNumber 123返回一个结果列表,而无需手动操作Linq生成的代码。
这就是我现在拥有的,并且正在工作:
class tdoc
{
public int xID {get; set;}
public int TransID { get; set; }
public System.String TransmittalName { get; set; }
public System.String FileName { get; set; }
public System.String DocumentNumber { get; set; }
public System.String REV { get; set; }
public System.DateTime REVDate { get; set; }
public System.String Title { get; set; }
public int? rID { get; set; }
public int? CODE { get; set; }
public System.String RTNTrans { get; set; }
public System.String RtnFile { get; set; }
}
class ObservableTrackDocument : ObservableCollection<TrackDocument>
{
public ObservableTrackDocument(DocControlClassesDataContext dataDc)
{
IEnumerable<tdoc> query = from f in dataDc.FilesTransmitteds
from r in dataDc.FilesReturneds
.Where(r => f.DocumentNumber == r.DocumentNumber && f.REV == r.REV)
.DefaultIfEmpty()
select new tdoc
{
xID = f.UID,
TransID = (int)f.TransID,
TransmittalName = f.TransmittalName,
FileName = f.FileName,
DocumentNumber = f.DocumentNumber,
REV = f.REV,
REVDate = (System.DateTime)f.REVDate,
Title = f.Title,
rID = r.UID,
CODE = r.CODE,
RTNTrans = r.RTNTrans,
RtnFile = r.FileName
};
foreach (tdoc Doc in query)
{
TrackDocument d = new TrackDocument();
d.xID = Doc.xID;
d.TransID = Doc.TransID;
d.TransmittalName = Doc.TransmittalName;
d.FileName = Doc.FileName;
d.DocumentNumber = Doc.DocumentNumber;
d.REV = Doc.REV;
d.REVDate = Doc.REVDate;
d.Title = Doc.Title;
d.rID = Doc.rID;
d.CODE = Doc.CODE;
d.RTNTrans = Doc.RTNTrans;
d.RtnFile = Doc.RtnFile;
this.Add(d);
}
}
}
我有一个TrackDocument类作为DataContext的一部分。为了使用联接进行查询,我必须在DataContext之外创建一个相等的类来查询(否则我会得到一个"查询中不允许显式构造实体类型xxx"的异常),然后我复制到DataContext类并用它填充我的observableCollection。这似乎有点倒退。难道没有更好的办法吗?