0

我正在尝试使用 select 子句从数据库查询中挑选出与指定名称字段匹配的对象,如下所示:

objectQuery = from obj in objectList
              where obj.Equals(objectName)
              select obj;

在我的查询的结果视图中,我得到:

base {System.SystemException} = {"Boolean Equals(System.Object)"}

我应该期待像Car, Make, 或Model

有人可以解释一下我在这里做错了什么吗?


有问题的方法可以在这里看到:

// this function searches the database's table for a single object that matches the 'Name' property with 'objectName'
public static T Read<T>(string objectName) where T : IEquatable<T>
{
    using (ISession session = NHibernateHelper.OpenSession())
    {
        IQueryable<T> objectList = session.Query<T>(); // pull (query) all the objects from the table in the database
        int count = objectList.Count(); // return the number of objects in the table
        // alternative: int count = makeList.Count<T>();

        IQueryable<T> objectQuery = null; // create a reference for our queryable list of objects
        T foundObject = default(T); // create an object reference for our found object

        if (count > 0)
        {
            // give me all objects that have a name that matches 'objectName' and store them in 'objectQuery'
            objectQuery = from obj in objectList
                          where obj.Equals(objectName)
                          select obj;

            // make sure that 'objectQuery' has only one object in it
            try
            {
                foundObject = (T)objectQuery.Single();
            }
            catch
            {
                return default(T);
            }

            // output some information to the console (output screen)
            Console.WriteLine("Read Make: " + foundObject.ToString());
        }
        // pass the reference of the found object on to whoever asked for it
        return foundObject;
    }
}

请注意,我IQuatable<T>在方法描述符中使用了接口“”。

我试图从数据库中提取的类的一个例子是:

public class Make: IEquatable<Make>
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Model> Models { get; set; }

    public Make()
    {
        // this public no-argument constructor is required for NHibernate
    }

    public Make(string makeName)
    {
        this.Name = makeName;
    }

    public override string ToString()
    {
        return Name;
    }

    // Implementation of IEquatable<T> interface 
    public virtual bool Equals(Make make)
    {
        if (this.Id == make.Id)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // Implementation of IEquatable<T> interface 
    public virtual bool Equals(String name)
    {
        if (this.Name.Equals(name))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

接口简单描述为:

public interface IEquatable<T>
{
    bool Equals(T obj);
}
4

2 回答 2

6

IQueryable<T>针对支持数据存储(在本例中为 SQL RDBMS)执行您的查询。您的 SQL RDBMS 不知道IEquatable<T>*,并且不能使用它的实现:查询函数必须可翻译为 SQL,并且obj.Equals(objectName)不可翻译。

您可以转换IQueryable<T>IEnumerable<T>并在内存中执行查询,但这太低效了。您应该更改签名以获取Expression<Func<TSource, bool>>谓词,并将名称检查器传递给它:

public static T Read<T>(Expression<Func<T,bool>> pred) {
    using (ISession session = NHibernateHelper.OpenSession()) {
        return session.Query<T>().SingleOrdefault(pred);
    }
}

您现在可以按如下方式使用此方法:

Make snake = Read<Make>(x => x.Name == "snake");


*此外,您IEquatable<T>未在您展示的方法中使用:该Equals(string)方法将有资格作为 的实现IEquatable<string>,但在您的Make类实现的接口列表中未提及。

于 2012-09-26T21:36:32.623 回答
0

您对 Equal 覆盖的调用之一可能会引发异常。

出于调试目的,尝试迭代而不是使用 Linq,您应该找出哪一个:

foreach(object obj in objectList)
{
    bool check = obj.Equals(objectName) // set a breakpoint here
}

至于导致异常的原因,请确保您的每个对象 Name 和 Id 属性都有值。

于 2012-09-26T21:35:50.770 回答