簡體   English   中英

將T-SQL轉換為LINQ-to-SQL

[英]Convert T-SQL to LINQ-to-SQL

我在SQL Server 2008數據庫中有一個表ContentHistory ,其列Content為數據類型xml, NOT NULL 此列存儲完整的XML文檔(包含一個或多個Article節點的Intersection根節點:

 <InterSection>
    <Article>
        <ID>1</<ID>
        ...other nodes/data
    </Article>
    <Article>
        <ID>2</<ID>
        ...other nodes/data
    </Article>
    <Article>
        <ID>3</<ID>
        ...other nodes/data
    </Article>
 </InterSection>

我編寫了T-SQL,它獲取XML數據並將其粉碎,以便為每個Article節點獲取一個結果行,以便我從ContentHistory表中選擇哪一行:

SELECT      T2.Articles.query('.')
FROM        ContentHistory
CROSS APPLY Content.nodes('/InterSection/Article') AS T2(Articles)
WHERE ... /* Filter records based on other columns in ContentHistory */

這很好但我不想將其稱為ASP.NET MVC應用程序中的存儲過程,因為到目前為止所有其他數據庫請求都是使用LINQ-to-SQL實現的。

所以問題是如何在LINQ中實現這一點(C#中的例子)?

staticboy,

使用Linq to SQL和Linq to XML結合使用。

首先從數據上下文獲取XML列。 假設您已為LINQ添加了.dbml文件到XML。

//Lets say you have database called TestDB which has your ContentHistory table
TestDBContext db = new TestDBContext();


//This will return as IQueryable. 
var result = db.ContentHistory.Select(p=>p.Content).Where(p=>p.Content == <your filter>);

您可以對var“result”執行foreach循環並獲得所需的結果。

和平

我知道這不是你想要的,但Linq to SQL完全支持存儲過程。 當您在DBML設計器中時,可以拖動您的sproc並讓LTS為您創建強類型方法。

這是我的問題的最終解決方案。 感謝@pwzeus的觀察。 這是我對LINQPad測試代碼的精確復制和粘貼:

var articles = 
    (from ch in ContentHistories
        .Where(ch=> ch.CompareTag == new Guid("D3C38885-58AB-45CB-A19C-8EF48360F29D")
            && ch.AgainstTag == new Guid("5832933B-9AF9-4DEC-9D8D-DA5F211A5B53")
            & ch.Created > DateTime.Now.AddDays(-3)) // Initial record filtering
    select ch.Content) // Only return the XML Content column
        .Elements("Article") // Get <Article> child elements
        .Select(article => new {
            Id = Convert.ToInt32(article.Element("Id").Value),
            AcessionNumber = (string)article.Element("AcessionNumber").Value,
            Headline = (string)article.Element("Headline").Value,
            PublicationDate = Convert.ToDateTime(article.Element("PublicationDate").Value),
            ArrivalDate = Convert.ToDateTime(article.Element("ArrivalDate").Value),
            Source = (string)article.Element("Source").Value,
            CopyRight = (string)article.Element("CopyRight").Value,
            Language = (string)article.Element("Language").Value,
            WordCount = String.IsNullOrEmpty(article.Element("WordCount").Value) ? 0 : Convert.ToInt32(article.Element("WordCount").Value),
            Snippet = (string)article.Element("Headline").Value,
            LeadParagraph = (string)article.Element("Headline").Value,
            ContentGuid = new Guid(article.Element("ContentGuid").Value)
        }) // Select and coerce data into new object
        .Skip(5) // Skip records for paging in web UI
        .Take(5) // Take only 1 page of records for display;

articles.Dump();

這里好奇的是生成的T-SQL:

-- Region Parameters
DECLARE @p0 UniqueIdentifier = 'd3c38885-58ab-45cb-a19c-8ef48360f29d'
DECLARE @p1 UniqueIdentifier = '5832933b-9af9-4dec-9d8d-da5f211a5b53'
DECLARE @p2 DateTime = '2009-09-27 12:43:20.386'
-- EndRegion
SELECT [t0].[Content]
FROM [ContentHistory] AS [t0]
WHERE ([t0].[CompareTag] = @p0) AND ([t0].[AgainstTag] = @p1)
    AND ([t0].[Created] > @p2)

在數據庫端只需要檢索盡可能多的行,但對於ContentHistory的每一行, Content字段包含一個XML文檔,其中包含可變數量的<Article>節點。 例如,如果我在SQL端使用.Skip(5).Take(5),那么我可能只跳過50篇文章,但如果行包含以下文章,則只返回5:

Row    ArticleCount
===    ============
1      10
2      5
3      20
4      10
5      5
6      1
7      1
8      1
9      1
10     1

您可以將XML從LINQ返回到SQL,然后根據我所知的情況使用LINQ to XML進行解析,或者對LINQ to SQL中的結果對象執行LINQ to XML解析。 我在擴展事件管理器應用程序中使用LINQ to XML解析XML,如下所示:

    private List<Bucket> ProcessXML(XDocument targetdata)
    {
    return new List<Bucket>(
                 from e in targetdata.Elements()
                 from d in e.Elements()
                 select new Bucket
                 {
                     count = (int)d.Attribute("count"),
                     truncated = (int)d.Attribute("trunc"),
                     bucket = (string)d.Element("value").Value
                 });
    }


    /*
    <BucketizerTarget truncated="0" buckets="256">
      <Slot count="2715303" trunc="0">
        <value>14</value>
      </Slot>
    </BucketizerTarget>
    */

public class Bucket
{
    internal string bucket;
    internal int count;
    internal int truncated;

    public string BucketSlot
    {
        get { return bucket; }
    }

    public int Count
    {
        get { return count; }
    }

    public int Truncated
    {
        get { return truncated; }
    }
}

目標源代碼中提供了其他示例。 它是codeplex上的開源,所以隨意查看你想要的所有內容。

我用Linqer 這需要花錢,但是從TSQL轉換為Linq-To-SQL查詢的工作非常出色。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM