Having trouble on Monotouch

45 views
Skip to first unread message

bgp

unread,
Oct 21, 2009, 7:34:22 PM10/21/09
to catnap-orm-discuss
Hi Tim,

Well I finally got around to trying Catnap on Monotouch. I had been
previewing the api on VS2008. I'm getting an exception during the
Domain Map in BasePropertyMap when it trys to get the setter method
with:

System.ArgumentException: The property 'Id' is not writable.

Everything works fine on my PC with VS2008, but on the iPhone
Simulator at run time I get the above. I'm using the same sqlite file
on both systems so I don't think thats the problem. I can read and
write to the db file with sqlite-net. I tried changing the column
names it fails on the first col it hits.

Any ideas? Have you been able to run Catnap on Monotouch?

Thanks in advance,

Bruce



Tim Scott

unread,
Oct 21, 2009, 9:57:01 PM10/21/09
to catnap-or...@googlegroups.com
Bruce,

The problem is that Id must have a private setter. For now, you can remedy
this in one of two ways.

1) Derive your entities from Catnap.Entity (in which case you would remove
the Id property from your derived classes), or

2) Make your Id like this:

public int Id { get; private set; }

I might prefer the former because it gives you proper equality comparison,
which you would otherwise probably need to implement yourself.

The is a problem, and I need to fix it. I think maybe I can use the SetId
method instead of reflection. Since I am requiring that method I might as
well use it wherever possible. This might also allow me to make it
unnecessary to explicitly map Id for every entity.

In the mean time, I should at least mention it in the Introduction.

Thanks for the feedback!

Tim

Tim Scott

unread,
Oct 21, 2009, 10:30:07 PM10/21/09
to catnap-or...@googlegroups.com
Option 3: get the latest.

IEntity.Id is no longer required to have a setter. Also, you no longer need
to map the Id property for any entity. If you do map it, then in must have
a setter (which can be non-public).

Tim

bgp

unread,
Oct 22, 2009, 12:37:14 PM10/22/09
to catnap-orm-discuss
Hi Tim,

Thanks for looking into this. I opted for #3. Once I removed the Id
mapping all worked well on the simulator. So I gave it a try on the
ipod touch I use for development. Unfortunately I'm getting the error
below during Domain.Configure ( remember same code works on the sim ):


Attempting to JIT compile method '(wrapper
managed-to-managed) System.Linq.Expressions.ParameterExpression
[]:System.Collections.Generic.ICollection`1.get_Count ()' while
running with --aot-only.

SOURCE: System.Core
TARGETSITE: System.Linq.Expressions.ParameterExpression[] ToArray
[ParameterExpression](IEnumerable`1)
STACKTRACE: at System.Linq.Enumerable.ToArray[ParameterExpression]
(IEnumerable`1 source) [0x00000]
at System.Linq.Enumerable.ToReadOnlyCollection[ParameterExpression]
(IEnumerable`1 source) [0x00000]
at System.Linq.Expressions.Expression.Lambda[Func`2]
(System.Linq.Expressions.Expression body, IEnumerable`1 parameters)
[0x00000]
at System.Linq.Expressions.Expression.Lambda[Func`2]
(System.Linq.Expressions.Expression body,
System.Linq.Expressions.ParameterExpression[] parameters) [0x00000]
at FosMobileIP.ConfigDao.LoadDomain () [0x00000]
at FosMobileIP.ConfigDao..ctor () [0x00000]

Looks like Monotouch hasn't quite got Linq expressions under control.
Have you tried this on a device yet?

Thanks again,
Bruce


On Oct 21, 10:30 pm, Tim Scott <tsc...@lunaversesoftware.com> wrote:
> Option 3: get the latest.
>
> IEntity.Id is no longer required to have a setter.  Also, you no longer need
> to map the Id property for any entity.  If you do map it, then in must have
> a setter (which can be non-public).
>
> Tim
>
> On 10/21/09 8:57 PM, "Tim Scott" <tsc...@lunaversesoftware.com> wrote:
>
>
>
> > Bruce,
>
> > The problem is that Id must have a private setter.  For now, you can remedy
> > this in one of two ways.
>
> > 1) Derive your entities from Catnap.Entity (in which case you would remove
> > the Id property from your derived classes), or
>
> > 2) Make your Id like this:
>
> > public int Id { get; private set; }
>
> > I might prefer the former because it gives you proper equality comparison,
> > which you would otherwise probably need to implement yourself.
>
> > The is a problem, and I need to fix it.  I think maybe I can use the SetId
> > method instead of reflection.   Since I am requiring that method I might as
> > well use it wherever possible.  This might also allow me to make it
> > unnecessary to explicitly map Id for every entity.
>
> > In the mean time, I should at least mention it in the Introduction.
>
> > Thanks for the feedback!
>
> > Tim
>

Tim Scott

unread,
Oct 22, 2009, 8:05:33 PM10/22/09
to catnap-or...@googlegroups.com
Ugh, that's depressing. No, I have not tried on a device yet. I have not
forked over the $400 to Novell yet. I would have hoped the simulator would
catch this. Guess that's why they call it a simulator and not an emulator.
It's also depressing that this error message is all but useless. Where in
my code is it coming from? Who knows? I thought that I was not doing any
runtime compilation, but I guess I must be. But where?

bgp

unread,
Oct 22, 2009, 9:04:44 PM10/22/09
to catnap-orm-discuss
Tim,

I suspect the problem is in Monotouch .Net assemblies not your code.
I'm knew to the Mac and iPhone world so debugging on the device is
still eluding me. The best I can tell the problem is with Linq
expressions down in the IEntityMap. Can you rewiite the
Domain.Configure code to avoid the Linq and Lamda expressions? I'll
be happy to be your test bench. The only thing I'm sure of is its
happening during Domain.Configure.

Let me know if there is anything I can try if it helps the cause.

Bruce

On Oct 22, 8:05 pm, Tim Scott <tsc...@lunaversesoftware.com> wrote:
> Ugh, that's depressing.  No, I have not tried on a device yet.  I have not
> forked over the $400 to Novell yet.  I would have hoped the simulator would
> catch this.  Guess that's why they call it a simulator and not an emulator.
> It's also depressing that this error message is all but useless.  Where in
> my code is it coming from?  Who knows?  I thought that I was not doing any
> runtime compilation, but I guess I must be.  But where?
>

Tim Scott

unread,
Oct 22, 2009, 10:03:14 PM10/22/09
to catnap-or...@googlegroups.com
Bruce,

Thanks.

I have added some diagnostic logging. Any chance you could build the latest
and try it again? Prior to Domain.Configure you need to do this:

Log.Level = LogLevel.Debug;

This will cause it to output some messages to the console during the
configure process. If you send me the console output leading up to the
error, I could perhaps pinpoint the problem and be able to create a test
case that I could submit with a bug ticket.

I saw some posts on the MonoTouch list with this same error, and the Novel
guys said to submit a ticket because they can address such issues case by
case.

Thanks again!

Tim

bgp

unread,
Oct 23, 2009, 10:13:57 AM10/23/09
to catnap-orm-discuss
Tim,

Ok, here is what I'm seeing. When run from the simulator your new
debug messages are as follows ( which makes sense ) :

Getting set method property.
Getting set method property.
Setting column name for value property.
Getting member expression for property for 'x => x.Value' of type
'ValuePropertyMap`2'
Getting set method property.
Getting set method property.
Setting column name for value property.
Starting unit of work a4364849-d192-420a-ad2e-bdce01228b96. Thread: 1
Connection opened
Preparing query: begin.
0 rows affected
Preparing query: Select * From ConfigPO.
Returning 18 rows
Disposing unit of work a4364849-d192-420a-ad2e-bdce01228b96. Thread: 1
Preparing query: end.
0 rows affected
Connection closed

When run from the iTouch we only get the exception ( same as post
above ). Best I can tell the parameters are being processed and
causing the error. I placed the debug statement directly before the
Domain.Configure as so:

Catnap.Common.Logging.Log.Level =
Catnap.Common.Logging.LogLevel.Debug;
Domain.Configure(
Map.Entity<ConfigPO>()
.Property(x => x.Name)
.Property(x => x.Value)
);

The exception is calling out the Linq expressions, could it be the
Lamda params?

Let me know whats next.

Bruce


On Oct 22, 10:03 pm, Tim Scott <tsc...@lunaversesoftware.com> wrote:
> Bruce,
>
> Thanks.  
>
> I have added some diagnostic logging.  Any chance you could build the latest
> and try it again?  Prior to Domain.Configure you need to do this:
>
> Log.Level = LogLevel.Debug;
>
> This will cause it to output some messages to the console during the
> configure process.  If you send me the console output leading up to the
> error, I could perhaps pinpoint the problem and be able to create a test
> case that I could submit with a bug ticket.
>
> I saw some posts on the MonoTouch list with this same error, and the Novel
> guys said to submit a ticket because they can address such issues case by
> case.
>
> Thanks again!
>
> Tim
>

Tim Scott

unread,
Oct 23, 2009, 10:34:07 AM10/23/09
to catnap-or...@googlegroups.com
I was thinking about this this morning. My logger simply wraps
Console.WriteLine. Is there a way to see console output when running on the
device? I was thinking I might need to also write to a file. I could add
the following to the logger API:

Logger.LogFile = [path];

You think I should do that?

Tim

bgp

unread,
Oct 23, 2009, 11:57:21 AM10/23/09
to catnap-orm-discuss
Actually that is how I got this output. For some reason the Xcode
Organizer does not have a Console tab when I plug in my device ( I
posted to the Monotouch Forums about this, still waiting to hear ) ,
so I added a file based Log class to Catnap. It writes the same
message you are sending to Console to the log file. And I know it
works I see the messages in the sim.

I dont think the logging is even getting a chance to write anything
because the error is occurring as the parameters are passed into
Domain.Configure. I even put my own logging messages in the Catnap
code. I placed one as the first line inside Domain.Configure, it
never gets there.



On Oct 23, 10:34 am, Tim Scott <tsc...@lunaversesoftware.com> wrote:
> I was thinking about this this morning.  My logger simply wraps
> Console.WriteLine.  Is there a way to see console output when running on the
> device?  I was thinking I might need to also write to a file.  I could add
> the following to the logger API:
>
> Logger.LogFile = [path];
>
> You think I should do that?
>
> Tim
>

Tim Scott

unread,
Oct 23, 2009, 3:26:53 PM10/23/09
to catnap-or...@googlegroups.com
Bruce,

Hmm. I have added logging during Domain construction. Most of what happens
there is just assigning to private fields. There is one call to Where, but
that's about it for any Linq stuff. Give it a spin if you can.

Wanna send me the file logging code you wrote? I would like to add that
capability to the Log class.

Tim

bgp

unread,
Oct 23, 2009, 5:10:21 PM10/23/09
to catnap-orm-discuss
Tim,

I dont think the problem is in Domain.Configure but rather the
parameters to it. The Map.Entity Properties seem to be the problem.
Just a guess.

I can now view the Xcode console, so if you have any thing else to try
let me know. Still getting the same error with the latest code.

Whats the best way to get you the Log class I use? I dont see
attachments on here and I'm not very good with SVN. The code isnt
pretty, but it works.

If you think it would help we could get together for a GoToMeeting
session and I could show you what I'm seeing ( I have a subscription).

Bruce

On Oct 23, 3:26 pm, Tim Scott <tsc...@lunaversesoftware.com> wrote:
> Bruce,
>
> Hmm.  I have added logging during Domain construction.  Most of what happens
> there is just assigning to private fields.  There is one call to Where, but
> that's about it for any Linq stuff.  Give it a spin if you can.
>
> Wanna send me the file logging code you wrote?  I would like to add that
> capability to the Log class.
>
> Tim
>

Tim Scott

unread,
Oct 23, 2009, 5:38:11 PM10/23/09
to catnap-or...@googlegroups.com
The best thing is to create an issue on the Google code site and attach an
svn patch file. Creating a patch is quite easy once you know how.

That said, in this case I would be very happy if you just send it in an
email or paste it in the body of the issue.

Tim

bgp

unread,
Oct 24, 2009, 4:43:01 PM10/24/09
to catnap-orm-discuss
Here you go. This log class create a file and keeps one back up. The
file size and file name are hard coded. You can make this as generic
as you want. This works on the devices.

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace FosMobileIP
{
public class Log
{
public static string GetLogFileName()
{
string logFile = "";
FileStream fs = null;
try{
string documents = Environment.GetFolderPath
(Environment.SpecialFolder.Personal);
logFile = documents + @"/FosMobile.log";

if ( !File.Exists(logFile) )
{
fs = File.Create(logFile);
}

} catch (Exception e )
{
Console.WriteLine("GetLogFile: " + e.Message);
}
finally
{
if ( fs != null ) fs.Close();
}
return logFile;
}

public static string GetLogFileText()
{
string s = "";
StreamReader sr = null;

try{
sr = new StreamReader(GetLogFileName());
s = sr.ReadToEnd();
} catch (Exception e )
{
Console.WriteLine("GetLogFileText: " + e.Message);
}
finally
{
if ( sr != null )
{
sr.Close();
sr.Dispose();
}
}
return s;
}

public static void DeleteLogFile()
{
try
{
string logFile = GetLogFileName();
if (File.Exists(logFile))
File.Delete(logFile);
}
catch ( Exception e )
{
Console.WriteLine("DeleteLogFile: " + e.Message);
}
}

public static void LogError(Exception ex)
{
LogError(GetLogFileName(), ex);
}

private static void LogError(string logFile, Exception ex)
{
string message = ex.Message +
"\r\nSOURCE: " + ex.Source +
"\r\nTARGETSITE: " + ex.TargetSite +
"\r\nSTACKTRACE: " + ex.StackTrace;

LogError(logFile, message);
}

public static void LogError(string sError)
{
LogError(GetLogFileName(), sError);
}

public static void Write(string sMessage)
{
LogError(GetLogFileName(), sMessage);
}

private static void LogError(string logFile, string sError)
{
StreamWriter sw = null;
try
{
if (!File.Exists(logFile))
{
FileStream fs = File.Create(logFile);
fs.Close();
}

sw = File.AppendText(logFile);
sw.WriteLine("\r\n" + DateTime.Now.ToString() + " : "
+ sError);
FileInfo fi = new FileInfo(logFile);
if (fi.Length >= 100000)
{
string newFileName = "Old_" + Path.GetFileName
(logFile);
newFileName = Path.Combine(Path.GetDirectoryName
(logFile), newFileName);
File.Copy(logFile, newFileName, true);
sw.Close();
DeleteLogFile();
}

Console.WriteLine(sError);
}
catch (Exception e1)
{
Console.WriteLine(e1.Message);
}
finally
{
if (sw != null) sw.Close();
}
}
}
}
Reply all
Reply to author
Forward
0 new messages