需要将SQL Server UNION语法转换为LINQ的帮助吗
我有下面的SQL,它工作得很好:需要将SQL Server UNION语法转换为LINQ的帮助吗,linq,sql-server-2005,union,Linq,Sql Server 2005,Union,我有下面的SQL,它工作得很好: SELECT Message, CreateDate, AccountId, AlertTypeId FROM dbo.Alerts UNION SELECT TOP (100) PERCENT Status, CreateDate, AccountId, (SELECT 10 AS Expr1) AS AlertTypeId FROM dbo.StatusU
SELECT Message, CreateDate, AccountId, AlertTypeId
FROM dbo.Alerts
UNION
SELECT TOP (100) PERCENT Status, CreateDate, AccountId,
(SELECT 10 AS Expr1) AS AlertTypeId
FROM dbo.StatusUpdates
WHERE AccountId = PassedInParameter
ORDER BY CreateDate DESC
我正在尝试将它转换为LINQ,但它的工作并不好:)显然,这里有很多错误-这只是一个粗略的开始。它没有考虑上面的temp列或order by条件,泛型/返回类型的歧义是我试图理解两种不同的返回类型:
public List<T> GetSomething<T>(Int32 accountId)
{
List<T> result;
using (DataContext dc = _conn.GetContext())
{
IEnumerable<Alert> alerts = (from a in dc.Alerts
where a.AccountId == accountId
select a);
IEnumerable<StatusUpdate> updates = (from s in dc.StatusUpdates
where s.AccountId == accountId
select s);
IEnumerable<T> obj = alerts.Union(updates);
result = obj.ToList();
}
return result;
}
以及,调用方法:
protected void LoadStatus()
{
repStatusUpdates.DataSource = _statusRepository
.GetUpdatesByAccountId<StatusUpdate>(_userSession.CurrentUser.AccountId);
repStatusUpdates.DataBind();
}
但这是次要的
再次感谢您的帮助。尝试以下操作(我已将StatusUpdate转换为警报,如果无法接受,您将不得不将警报转换为StatusUpdate,或者创建一个新类):
我之所以选择“最后一个”,是因为您不必为所有未使用的结果构建新警报
这将为您提供警报列表
在这种情况下使用泛型是很难做到的。例如,您不能这样做:
IQueryable alerts=(来自a in_alerts
其中a.AccountId==AccountId
选择a)
因为这会隐式地将a转换为T类型。即使您试图限制T实现或继承的内容:
public List<T> GetSomething<T>(Int32 accountId) where T : IAlert// Interface that both StatusUpdates and IAlert implement
public List<T> GetSomething<T>(Int32 accountId) where T : Alert
public List<T> GetSomething<T>(Int32 accountId) where T : AlertBase // Base class for both Status and Alert
如果您同时拥有Alert和StatusUpdate实现IAlert,则可以将其重写为:
IQueryable<IAlert> alerts = (from a in dc.Alerts
where a.AccountId == accountId
select a);
IQueryable<IAlert> updates = (from s in dc.StatusUpdates
where s.AccountId == accountId
select s)
.OrderByDescending( x => x.CreateDate)
.Take(100);
var obj = alerts.Union(updates);
result = obj.ToList();
IQueryable警报=(来自dc.alerts中的
其中a.AccountId==AccountId
选择a);
IQueryable updates=(来自dc.StatusUpdates中的s
其中s.AccountId==AccountId
选择(s)
.OrderByDescending(x=>x.CreateDate)
.取(100);
var obj=alerts.Union(更新);
结果=对象ToList();
这是我将采取的路线,而不是传入一些未知类型并试图限制它实现或继承的内容,因为强制转换到该类型可能仍然无效。您只能接受相同类型序列的并集。您需要将警报和更新转换为通用类型的序列,然后使用union。可以使用匿名类型执行此操作。如果这些类型没有任何共同点,则特别有用
//this is a hack and probably not what you would want to use.
var alerts =
from a in dc.Alerts
where a.AccountId == accountId
select new { Alert = a, StatusUpdate = (StatusUpdate)null };
var updates =
from s in dc.StatusUpdates
where s.AccountId == accountId
select new { Alert = (Alert)null, StatusUpdate = s };
//both are sequences of anonymous type with properties:
// Alert (of type Alert)
// StatusUpdate (of type StatusUpdate)
var obj = alerts.Union(updates);
如果您有共同的字段,除了包含已知字段外,您仍然会使用匿名类型
var alerts =
from a in dc.Alerts
where a.AccountId == accountId
select new
{
a.Message, //assuming is a string
Status = (string)null,
a.CreateDate,
a.AccountId,
a.AlertTypeId //assuming is an int
};
var updates =
(from s in dc.StatusUpdates
where s.AccountId == accountId
select new
{
Message = (string)null,
s.Status, //assuming is a string
s.CreateDate,
s.AccountId,
AlertTypeId = 10 //this should handle the "10 AS AlertTypeId" part
}).OrderByDescending(s => s.CreateDate);
var obj = alerts.Union(updates);
关键是两个匿名类型具有相同确切类型的相同确切属性。然后你就可以把两者结合起来。嗨,梅里特。谢谢我喜欢你的代码,因为它似乎回答了我试图在原始SQL中完成的所有事情。但是编译器在许多不同的地方抱怨,即“new”语句。现在已经很晚了,我需要去睡觉了,但我明天会再看一遍,并报告我在你的代码中遇到的错误。同时,我发布了我当前更新的代码。再次感谢。是的,只需移除“a”前面的新图标。编辑后的回答编辑后的回答可以更好地解释为什么我不在这里使用匿名类型或泛型方法。Merritt-我喜欢你所说的并同意,但我没有访问IAlert或IStatusUpdate的权限。警报和状态更新来自我的LINQ表,我正在通过Repository操作它们,所以我有ISTATUSHUPDATEREPository和IAlertRepository,但我不确定这是否有用?我已经在我的新编辑中发布了这些接口。引发的异常不是由FriendAccountId.Concat(new[]{accountId})引发的;但是在最后的回报声明中(尽管我个人的感觉是错误确实发生在工会)。嗨,杰夫。谢谢我试着用你扔的球跑,并在上面发布了我的编辑。我喜欢你发布的“公共字段”代码,因为这是我正在尝试做的,但我还需要s.Status和a.Message作为一个(临时)列显示(你是正确的,它们并不相同)。再次感谢。我不知道你想要那个角色。我已经更新了我的答案。关键是要使两组的类型完全相同。嗨,杰夫。非常感谢。我正试图找出如何使这个方法类型具体化,因为这对我正在做的事情更有意义,但根据我对Merritt的回复,我遇到了问题。如果你对如何做有任何其他想法,请告诉我。否则,等我弄明白了,我会回去报告的。。。再次感谢!这个奇怪的错误消息可能意味着您的LinqToSQL查询对于LinqToSQL来说太复杂了,甚至如此复杂以至于他们的测试没有考虑到任何人编写它。我不认为将其作为通用方法的意义。此外,您不希望在联合后执行Take-after-you-union,因为这不是您在SQL查询中执行的操作。不喜欢创建状态更新/警报对列表,其中一个始终为null。在这里使用非匿名类型将限制其在数据绑定之外的可用性,并且可能需要反射来查找属性值。FriendAccountId.Concat(new[]{accountId})是否引发异常;?
public List<T> GetSomething<T>(Int32 accountId) where T : IAlert// Interface that both StatusUpdates and IAlert implement
public List<T> GetSomething<T>(Int32 accountId) where T : Alert
public List<T> GetSomething<T>(Int32 accountId) where T : AlertBase // Base class for both Status and Alert
public List<IAlert> GetSomething(Int32 accountId)
public interface IAlert
{
int AccountId { get; set; }
int AlertTypeId { get; set; }
DateTime CreateDate { get; set; }
string Message { get; set; }
}
IQueryable<IAlert> alerts = (from a in dc.Alerts
where a.AccountId == accountId
select a);
IQueryable<IAlert> updates = (from s in dc.StatusUpdates
where s.AccountId == accountId
select s)
.OrderByDescending( x => x.CreateDate)
.Take(100);
var obj = alerts.Union(updates);
result = obj.ToList();
//this is a hack and probably not what you would want to use.
var alerts =
from a in dc.Alerts
where a.AccountId == accountId
select new { Alert = a, StatusUpdate = (StatusUpdate)null };
var updates =
from s in dc.StatusUpdates
where s.AccountId == accountId
select new { Alert = (Alert)null, StatusUpdate = s };
//both are sequences of anonymous type with properties:
// Alert (of type Alert)
// StatusUpdate (of type StatusUpdate)
var obj = alerts.Union(updates);
var alerts =
from a in dc.Alerts
where a.AccountId == accountId
select new
{
a.Message, //assuming is a string
Status = (string)null,
a.CreateDate,
a.AccountId,
a.AlertTypeId //assuming is an int
};
var updates =
(from s in dc.StatusUpdates
where s.AccountId == accountId
select new
{
Message = (string)null,
s.Status, //assuming is a string
s.CreateDate,
s.AccountId,
AlertTypeId = 10 //this should handle the "10 AS AlertTypeId" part
}).OrderByDescending(s => s.CreateDate);
var obj = alerts.Union(updates);