2014-11-06 59 views
0

我正在使用Visual Studio Express 2013和SQL Server Express 2014编写一个使用LINQ to SQL来访问数据的WPF应用程序。我的意图是完整的CRUD功能,使用映射到observableCollections的各种UI元素。到目前为止,一切正常,但我只是使用映射到datagrid的单个表。我想用两个表中的左连接的结果呈现单个数据网格,因此在dbml布局中我创建了一个新表,并使用存储过程作为数据源IDE生成的代码如下所示:WPF LINQ to SQL类定制

[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); 
     } 
    } 
} 

但DataContext的未填充的表,因为该存储过程不能用作源。它发生,我认为我需要在构造在这里添加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); 
     } 
    } 
} 

但是,这并不工作,要么(我remvove“源“引用了原始异常原因的dbml布局中的TrackDocument类属性列表的存储过程)。 。 。出于某种原因,编译器无法协调将查询项目转换为TrackDocument类。

我是否需要重写TrackDocument类中IDE生成的方法之一以执行普通单表格情况下会导致TrackDocuemnts集合的查询?如果是这样,你能给我一个如何重写的例子吗?类代码在自动生成的文件中,所以我知道我不能在那里手动添加东西。 。 。

我希望这很清楚。 。 。我很困惑这种语言来描述这些事情。

谢谢,保罗

+0

我想你会想要将存储过程与使用System.Data.Linq.Mapping.FunctionAttribute的函数相关联。 – juharr 2014-11-06 18:54:20

+0

@juharr我通过将存储过程拖放到设计器布局中来解释你所说的将存储过程添加到DataContext中。 。 。我已经完成了。它显示为一种方法,可以与类的行为相关联,但只能作为插入,删除或更新。如果我手动更改designer.cs文件,那么它将被覆盖,因为它是由IDE自动生成的。所以我不确定你的意思。 。 。对不起:) :) – 2014-11-06 19:12:48

+0

@juharr我试图把行改成'[global :: System.Data.Linq.Mapping.FunctionAttribute(Name =“dbo.ListAllDocuments”)]'但编译器告诉我这只是适用于方法。 。 。 – 2014-11-06 21:04:09

回答

1

保罗,

尝试使用视图,而不是一个存储过程。这会给你Linq表的功能。

如果您必须使用存储过程,即返回数据集,则需要为存储过程的返回类型创建实体。在DBML设计器中单击存储过程时,请检查属性的“返回类型”(这是将接收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生成的代码。

+0

你能举个例子吗?我没有被绑定到存储过程,实际上认为找到一种明确查询的方式会更好,以免为了发展我对实际正在发生的事情的理解。 – 2014-11-06 20:53:55

+0

我发布了我的工作。 。 。不确定它会被淘汰。但是我也改变了SP的返回类型,但无济于事,因为我仍然无法使用SP创建DataContext表。 – 2014-11-07 00:23:41

+1

保罗,抱歉,极端延迟...值班电话。我修改了我的回复,希望能够澄清您的问题。关于SP,返回类型必须反映SP返回的内容。如果您的SP返回Document,Name,Date,...,那么您必须添加一个实体来存放Linq要映射到的这些字段和数据类型。在GUI设计器中,您可以右键单击>新建>实体并生成一个自定义“表格”来保存结果。这又会导致数据类型问题,所以最好的办法是尝试一个可以直接映射的视图。 – 2014-11-24 15:23:31

0

这是我现在有,并且正在努力:

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不允许在查询中”异常),然后我复制并填充我的observableCollection与DataContext类。这似乎有些倒退。 。 。没有更好的方法吗?