Linq to sql中的异常

时间:2009-11-05 18:04:22

标签: linq-to-sql exception

我的查询是:

var ReadAndUnreadMessages =
        (from m in MDB.Messages
         orderby m.Date descending
         where m.ID_Receive == (Guid)USER.ProviderUserKey && m.Delete_Admin == false
         select new AllMessages()
         {
             id = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Message,
             parent = (Guid)(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Message_Parent,
             sender = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Sender,
             receiver = (Guid)USER.ProviderUserKey,
             subject = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Subject.Subject1.ToString() == "Other" ?
                           (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Other_Subject
                           :
                           (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Subject.Subject1.ToString(),
             body = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body.Length > 26 ?
                     (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body.Substring(0, 25) + "..."
                     :
                     (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body,
             date = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Date.ToShortDateString(),
             read =(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).IsRead,
             finished = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).IsFinished,
             count = MessageClass.LoadAll(m.ID_Message).Count
         }).ToList();

,例外是:

  

参数'value'是错误的类型。预期的'消息'。实际的'System.Object'。

这意味着什么?

LoadMessageChildren:

public static ArrayList LoadMessageChildren(Guid Parent)
{
    ArrayList arr = new ArrayList();
    Guid id = Parent;
    while (id != Guid.Empty)
    {
        arr.Add(LoadMessage(id));
        try
        {
            id = (Guid)MDB.Messages.Single(a => a.ID_Message_Parent == id).ID_Message;
        }
        catch
        {
            id = Guid.Empty;
        }
    }
    return arr;
}

LoadMessage:

public static Message LoadMessage(Guid id)
{
    var mess = from m in MDB.Messages
               where m.ID_Message == id
               select m;

    return mess.Single();
}

3 个答案:

答案 0 :(得分:5)

代码不可读,并且是代码重复的错误情况(以及LoadMessageChildren的多次执行)。
首先,请考虑以下事项:

from m in MDB.Messages
     orderby m.Date descending
     where m.ID_Receive == (Guid)USER.ProviderUserKey && m.Delete_Admin == false
     let children = LoadMessageChildren(m.ID_Message)
     let lastChildMessage = children.Last()
     select new AllMessages()
     {
         id = lastChildMessage.ID_Message, 
         ...
     }

这可以解决您的问题,因为它是might be caused by using the [] indexer 除此之外,尚不清楚发布的代码是否导致异常。

答案 1 :(得分:0)

错误很可能是由ArrayList

引起的

问题是LINQ旨在与实现System.Collections.Generic.IEnumerable<T>接口的泛型集合一起使用。 ArrayList是一个非泛型集合,在内部将所有内容存储为Object。因此,当您从ArrayList中检索某些内容时,需要将其强制转换为Message。 查看您的错误消息,它看起来像某个Message对象,但是当发生该引用时,您的ArrayList中的实例(Object)不会被转换为Message对象。此外,ArrayList未实现IEnumerable<T>接口,这可能会在某些情况下让您陷入麻烦。

如何解决?

我建议您更改LoadMessageChildren的实施,以使用generic listList<Message>):

public static List<Message> LoadMessageChildren(Guid Parent)
{
    List<Message> arr = new List<Message>();
    Guid id = Parent;
    while (id != Guid.Empty)
    {
        arr.Add(LoadMessage(id));
        try
        {
            id = (Guid)MDB.Messages.Single(a => a.ID_Message_Parent == id).ID_Message;
        }
        catch
        {
            id = Guid.Empty;
        }
    }
    return arr;
}

在检索/引用项目方面,您还必须更改与通用列表交互的代码。但那只是语法。由于存在与列表和项目交易的等效方法。

ArrayList切换到List<T>,在性能和编译时验证方面也有优势。 ArrayList基本上是.Net Framework 1.0版本的继承,当时没有对泛型的支持,它只是出于兼容性原因而被保留在框架中。 有更大的benefits for using generics

更新的答案:

方法”System.Collections.Generic.List'1 [Message] LoadMessageChildren(System.Guid)'没有支持的SQL转换“您获得的异常是由事实引起的您的LoadMessageChildren方法未映射到数据库中的存储过程或用户定义的函数。

您不能在LINQ to SQL查询中调用任何常规C#方法。 LINQ to SQL object model将查询中的方法解释为存储过程或用户定义的函数。因此,引擎基本上寻找一种名为LoadMessageChildren的方法,该方法映射到数据库中的存储过程或用户定义的函数。因为没有映射,它会告诉您no supported translation to SQL已找到。 LINQ to SQL object model链接向您展示了如何使用方法属性来映射执行存储过程的方法。

您现在有几个选择:

  1. 创建常规C#方法调用的存储过程
  2. 重写LINQ查询以使用joins选择子消息

答案 2 :(得分:0)

我唯一看到你使用LoadChildMessages()的方法是让孩子的消息计数......除非我错了,我认为你可以把它写成一个连接。您在查询中执行了大量查询,这些查询似乎不是必需的,并且可能导致对数据库的多次命中。我的问题是,为什么你的dmbl / sql数据库中没有关系,以便LinqToSql知道创建一个属性为List<Message> ChildMessages

但这是我的看法:

var query = from message in MDB.Messges
            join childmessage in MDB.Messages.Where(child => child.ID_Message_Parent == message.ID_Message) into childMessages
            from childMessage in childMessages.DefaultIfEmpty() // This creates a 
            // left outer join so you get parent messages that don't have any children 
            where message.ID_Receive == (Guid)USER.ProviderUserKey && message.Delete_Admin == false
            select new AllMessages()
            {
                id = message.ID_Message,
                parent = message.ID_Message_Parent,
                sender = message.ID_Sender,
                receiver = (Guid)USER.ProviderUserKey,
                subject = message.Subject.Subject1.ToString() == "Other" ?
                           message.Other_Subject
                           :
                           message.Subject.Subject1.ToString(),
                body = message.Body.Length > 26 ?
                     message.Body.Substring(0, 25) + "..."
                     :
                     message.Body,
                date = message.Date.ToShortDateString(),
                read =message.IsRead,
                finished = message.IsFinished,
                count = childMessage.Count() // This might have to be this
                //count = childMessage == null ? 0 : childMessage.Count()
            };

var ReadAndUnreadMessages = query.ToList();

但很难说,因为我无法运行代码......如果有效,请回复并告诉我。

注意:我建议使用一个链接到DataContext.Log属性的类,该类将生成的TSQL代码写入调试器窗口。这是关于writing your own的文章。当我对数据库进行不必要的调用时,它确实帮助我。