[英]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.