DA LINQ support for iOS/MonoTouch/Xamarin

Hello Helmut.

DA LINQ was disabled on MonoTouch due to some technical issues in processing DA LINQ queries on real devices. If you want to use the DA LINQ on iOS device you need to use the Data Abstract for Portable Class Library build.

Thanks

Hello Andrey

thanks for your answer, but i get this error when i use the PCL-Library.

Is there any Sample/Demo how to use the DA PCL template ?

Thanks

Hello Helmut.

Please note that:

  1. LinqRemoteDataAdapter is defined in the assembly RemObjects.DataAbstract for all platforms except desktop .NET (I am inconvenience that is going to change in the next release)

  2. Only asynchronous queries are supported:

         var q = (from x in linqRemoteDataAdapter.GetTable<Clients>() select x);
         IQueryable[] Queries = new IQueryable[] { q };
         linqRemoteDataAdapter.BeginExecute(
             Queries,
             delegate(IAsyncResult ar)
             {
                 linqRemoteDataAdapter.EndExecute(ar);
                 Dispatcher.BeginInvoke(new ProcessSelectClientsResultCb(ProcessSelectClientsResult), q.ToList<Clients>());
             },
             null);
    

If the async/await pattern is already supported by Xamarin.iOS I can provide you a set of extension method that will make such calls a lot easier to write.

Thanks

Hello Andrey,

async/await pattern is already supported by Xamarin.iOS. Can you provide me a set of extension method ?

Thanks

Hello Helmut.

Please define the next extension methods

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RemObjects.DataAbstract.Linq
{
    public static class Extensions
    {
        public static Task<List<T>> LoadListAsync<T>(this LinqDataAdapter self, IQueryable<T> query) where T : class, new()
        {
            return Task.Factory.FromAsync<IQueryable[], List<T>>(self.BeginExecute,
                (ar) => { self.EndExecute(ar); return query.ToList<T>(); },
                new IQueryable[] { query }, null);
        }
        public static Task<DABindingList<T>> LoadBindableListAsync<T>(this LinqDataAdapter self, IQueryable<T> query) where T : class, new()
        {
            return Task.Factory.FromAsync<IQueryable[], DABindingList<T>>(self.BeginExecute,
                (ar) => { self.EndExecute(ar); return query.ToDABindingList<T>(); },
                new IQueryable[] { query }, null);
        }
        public static Task ApplyChangesAsync(this LinqDataAdapter self)
        {
            return Task.Factory.FromAsync(new Func<AsyncCallback, object, IAsyncResult>(self.BeginApplyChanges), new Action<IAsyncResult>(self.EndApplyChanges), (object)null);
        }
    }
} 

and use them the next way:

var list = await fDataModule.DataAdapter.LoadDataAsync((from x in fDataModule.DataAdapter.GetTable<Clients>() select x); 

Thanks.

Hi,

When using this technique, i get the error:

No method ‘AsQueryable’ exists on type ‘System.Linq.Queryable’.

What am i missing?

Regards,

Hello

Could you provide some more details on this error?

Thanks in advance

Hi,

Thanks for the reply. I’m using Xamarin and the DataAbstract Portable Class Library, and what i did was doing was:

			var rda = Relativity.Instance.DataAdapter;
			var q = (from x in rda.GetTable<Categories>() select x);
			IQueryable[] Queries = new IQueryable[] { q };
			try {
				var list = await rda.LoadListAsync<Categories>((from c in rda.GetTable<Categories>() select c));
				foreach(Categories cat in list) {
					System.Diagnostics.Debug.WriteLine( cat.CategoryName );
				}
			} catch (System.Exception ex) {
				System.Diagnostics.Debug.WriteLine(ex.Message);
			}

then i added a line:

			var aq = q.AsQueryable<Categories>();

and it worked, apparently something was not getting linked.

–

But now may problem is another, i already created another post. And it is, that since everything is “async” the LoginAsync never finishes and i allwasy get “Session not found”

There is a chance that you forgot to add System.Linq’ namespace to the uses section.

.AsQueryable is an extension method, so compiler won’t be able to resolve it unless the namespace containing the extension methods is references.

As for the other issue - as temporary workaround you could call LoginAsync when the main form of your app is displayed, until your support request is properly processed,

Hi,
now i’ve updated to DA8 Version and started a new sample DA-PCL project connecting to a custom DA-Server

LogonAsync passed trough, but when i call

`async void GetAerzte()
{

        try
        {
            var list = await fDataModule.DataAdapter.LoadListAsync((from x in fDataModule.DataAdapter.GetTable<AERZTE>() select x));
            foreach (AERZTE arzt in list)
            {
                Console.WriteLine("ArztID: " + arzt.AdresseID.ToString());
            }
        }
        catch (System.Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }`.

I get the Exception: " The requested feature is not implemented."

What’s wrong, missing something ?

Best regards

Hello

Could you provide more information on this? Like stacktrace, where exactly the exception happens, application type and platform (Android or iOS) etc?

Hi
I think it’s a Xamarin problem, because it’s running on Xamarin.Android and WP8 but not on Xamarin.iOS.
I contact the Xamarin Support.

Thanks
Helmut

Hello

Well, it seems there is a non-implemented feature (or a bug) in iOS ExpressionCompiler
Still I was able to retrieve data from Data Abstract server. Code I used was

		private static async void DATest()
	{
		try
		{
		var dm = new DataModule ();

		var list = await dm.DataAdapter.LoadListAsync (from x in dm.DataAdapter.GetTable<Customers> ()
				select new {x.Name} );
		Console.WriteLine (list.Count);
			foreach (var item in list) {
				Console.WriteLine (	item.Name);
			}
		}
		catch(Exception ex)
		{
			Console.WriteLine (ex.ToString());
		}
	}

The inconvenience is that one has to explicitly list fields he need to retrieve. At the same time this approach allows to save the precious network bandwidth (because only data that is needed is fetched from the server)

Yep, this works.
I reported this to XAMARIN

Thanks a lot an best regards
Helmut

Hi Anton,
your sample code works only on the simulatur, not on a device.

I think, there are some bugs in the PCL-DLL’s for iOS (RemObjects.DataAbstract.dll) PPM.xlsx.zip (19.4 KB) . I’ve attached a Excell file with the result of the Xamarin Mobility scan against your dll’s.
Android and WP are fine (100% compatible) but not iOS (and Windows Store).

Is this a Xamarin issue??
thanks
Helmut

Hello

Well, if it works in emulator but fails on a real device -I’d say that this is an issue of framework deployed on the real device. What exactly error did you get?

Re scan.xamarin.com - sometimes it throws a ‘false positive’ warnings. F.e. it complains on methods in RemObjects.SDK.dll like

Array Array.CreateInstance (Type, int)
void Array.SetValue (object, int)
object Array.GetValue (int)

while they are present in the Windows Runtime. while reflection-related methods are not present in the WinRT AS IS it seems that method calls in a PCL like

public static Type[] TestCall(Assembly source)
{
	return source.GetExportedTypes();
}

are internally mapped to supported API (exactly this method can be called from a Windows Store app despite native Store apps use different API to retrieve types list)

As for the Xamarin.iOS warnings - call like

Type type = Expression.Constant((object) 5.5).Type;

does NOT result in scanner warnings when this call is performed directly in a Xamamrin.iOS app while you get a warning about

System.Type ConstantExpression.Type { get; }

So it seems that this scan tool’s warnings should be treated as warnings, not real errors.

Hi Anton,

sorry, my mistake. It runs on device

Thanks in advance
Helmut

Hello

Just to confirm (this thread is rather long :wink: )
You were able to successfully access data using Data Abstract/PCL on both iOS and Android devices running Xamarin.iOS and Xamarin.Android apps respectively?

Hello,
yes, that’s right. But only this method is running on all devices (iOS, Android and WP8)

And this method is running only on Android and WP8, but not on iOS

Update:
Seems it should be possible, with some efforts, to use DABindingList with iOS (despite still alive bug that prevents LINQ engine from materializing Table Definition classes when their columns are not listed explicitly):

// 1 Load data
var query = from x in fDataModule.DataAdapter.GetTable<Customers>() select new { x.Id, x.Name /* list all columns here */ };
var anonymousList = await fDataModule.DataAdapter.LoadListAsync(query);

// 2.1. Create empty BindingList
var bindingList = new DABindingList<Customers>(fDataModule.DataAdapter);

// 2.2. Load BindingList from an enumerable
// Later a mapper class would be implemented here to remove the need to expicitly list all TableDefs columns
anonymousList.ForEach(x => bindingList.Add(new Customers { Id = x.Id, Name = x.Name }));
// 2.3. Clear the 'data changed' flag
bindingList.CancelChanges();

// 3. Bind the data. Changed made in the grid can are queued as DeltaChanges and can be applied to the server
dataGridView1.DataSource = bindingList;