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

WPF LINQ to SQL类自定义

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。这似乎有点倒退。难道没有更好的办法吗?