praeclarum / sqlite-net

Simple, powerful, cross-platform SQLite client and ORM for .NET
MIT License
4.07k stars 1.42k forks source link

FindColumnWithPropertyName fails and crash, why? #93

Open Emasoft opened 12 years ago

Emasoft commented 12 years ago

In Monotouch, I get this error using SQLite-net:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at SQLite.TableQuery`1[MyApp.MyVocabEntry].CompileExpr (System.Linq.Expressions.Expression expr, System.Collections.Generic.List`1 queryArgs) [0x00520] in /Users/Emanuele/Projects/DictionaryForIPhone/SQLite.cs:2211 

This is the code:

using(SQLiteConnection sqlcon = new SQLiteConnection(dBFilePath))
                {
                        var results=    from s in sqlcon.Table<MyVocabEntry> ()
                            where s.Word == text_to_search
                            select s;
                }

the error is in this lines of SQLite.cs (MonoDevelop stops on the FindColumnWithPropertyName line):

} else if (expr.NodeType == ExpressionType.MemberAccess) {
                var mem = (MemberExpression)expr;

                if (mem.Expression.NodeType == ExpressionType.Parameter) {
                    //
                    // This is a column of our table, output just the column name
                    // Need to translate it if that column name is mapped
                    //
                    var columnName = Table.FindColumnWithPropertyName (mem.Member.Name).Name;
                    return new CompileResult { CommandText = "\"" + columnName + "\"" };
peterhuene commented 12 years ago

Looks related to some recent changes having to do with column mappings. Could you include the property definition for MyVocabEntry.Word (including any attributes)? Perhaps that might shed some light on the issue.

Emasoft commented 12 years ago

Ok, thanks. Here is the MyVocabEntry class:

public class MyVocabEntry
                {

[PrimaryKey, AutoIncrement]
public int ID { get; set; }

[Indexed]
public int EntryIndex { get; set; }

public string StemLemma { get; set; }

public string Etimology { get; set; }

[Indexed]
public string Word { get; set; }

public string PartOfSpeech { get; set; }
public string Morphology { get; set; }
public string Definitions { get; set; }

[Indexed]
public string Synonyms { get; set; }

[Indexed]
public string Antonyms { get; set; }

public override bool Equals (object obj)
{
if (obj is MyVocabEntry) {
    return this.GetHashCode() == obj.GetHashCode();  
}  else {
    return base.Equals(obj);
}
}

public override string ToString ()
{
return string.Format ("[MyVocabEntry]") + "," + EntryIndex + "," +Word + "," + StemLemma;
}

public override int GetHashCode ()
{
unchecked
    {
        int result = 37; // prime

        result *= 397; // also prime
        if (EntryIndex != 0)
            result += EntryIndex.ToString().GetHashCode();

        result *= 397;
        if (Word != null)
            result += Word.GetHashCode();

        result *= 397;
        if (StemLemma != null)
            result += StemLemma.GetHashCode();

        return result;
    }
}

                }
Emasoft commented 12 years ago

I solved the problem. In MonoTouch you need to add the "Serializable" and "Preserve All Members" attributes before the class declarations, otherwise the compiler removes some properties metadata at compile time:

[Serializable]
[Preserve(AllMembers=true)]
public class MyVocabEntry
                {
                   ...
                 }

I suggest you to add this info to the documentation wiki, I wasted a lot of time on this. Now it works beautifully. Great library.