I’m using CouchbaseLite with Xamarin, and am following some example code from the CouchbaseConnect2014 project for creating a snapshot of our database with the intention of bundling it, and preloading it in our app on first run. I’m getting as far as loading the created database into our project, but am having trouble getting the attachments to come through.
When I try to retrieve an attachment, I am getting a InternalServerError exception. The generated cblite file seems to load ok, but when I try to retrieve an attachment from a particular document, I get the an exception when it tries to access the attachment’s content.
I import the cblite file and the attachments as embedded resources into my project, and access them with the Xamarin specific calls below. This “seems” to work fine, without error. I am getting valid stream objects.
Here is my code for loading the database.
var manager = Manager.SharedInstance;
Debug.Assert(manager != null, "Could not access manager");
if (manager.GetExistingDatabase (Config.Instance.DbName) != null)
{
Debug.WriteLine("Found existing local database");
database = manager.GetDatabase (Config.Instance.DbName);
}
else
{
var resourceName = Assembly.GetAssembly (typeof(myappname.App)).GetManifestResourceNames ().Where (x => x.EndsWith ("baseline_db.cblite", StringComparison.CurrentCultureIgnoreCase)).Single ();
Stream baselinedb = Assembly.GetAssembly (typeof(myappname.App)).GetManifestResourceStream (resourceName);
// This returns all resources, because I don't know how to do linq queries correctly...
var resources = Assembly.GetAssembly (typeof(myappname.App)).GetManifestResourceNames ().Where (x => x.EndsWith (".blob", StringComparison.CurrentCultureIgnoreCase));
Dictionary<string, Stream> attachments = new Dictionary<string, Stream> ();
foreach (string sz in resources) {
if (sz.EndsWith (".blob")) {
attachments.Add (sz, Assembly.GetAssembly (typeof(myappname.App)).GetManifestResourceStream (sz));
}
}
Debug.WriteLine("Creating local database from baseline_db" );
database = manager.GetDatabase (Config.Instance.DbName);
manager.ReplaceDatabase(Config.Instance.DbName, baselinedb, attachments);
}
Here is what I am doing when I try to access the attachments.
public Attachment GetAttachment(string id, string name)
{
if (id == null || id == string.Empty)
{
return null;
}
var doc = database.GetExistingDocument (id);
if (doc == null)
{
return null;
}
var attachment = doc.CurrentRevision.GetAttachment (name);
if (attachment == null || attachment.Metadata == null)
{
return null;
}
return attachment;
}
…
var attachment = Couchbase.Instance.GetAttachment (Id, "cover.png");
if(attachment != null && attachment.Content != null) // Exception occurs here when Content is accessed
{
_imageBytes = attachment.Content as byte[];
}
The attachment is partially filled out, but it’s Content and ContentStream members are null. I suspect it may not like the dictionary of streams that I pass in to the ReplaceDatabase function, but I was unable to find any documentation on what it expects. Am I doing anything obviously wrong? Do I manually need to copy my attachments to a specific location? I was assuming/hoping that the ReplaceDatabase call would take the streams and put them in the right spot. Any info appreciated.