LINQPad Driver + LINQ to BigQueryによるBigQueryデスクトップGUIクライアント
- 2015-10-25
Happy signed!
LINQ to BigQueryのLINQPad Driverが
- サイドバーでのスキーマのツリー
表示 - thisを
読 み込 んでいるConnectionで認証 済 みのBigQueryContextに変更 関連 するアセンブリと名前 空間 を自動 で読 み込 み- スキーマに
対応 するクラスを動的 に生成 /読 み込 み - ちょっとしたユーティリティDumpの
追加 (DumpRun/DumpRunToArray/DumpChart/DumpGroupChart) - もちろんクエリのローカルでの
保存 /読 み込 みが可能
です。
- TableDateRangeに
対 するサポート - DateTimeの
自動 変換 (一部 のBigQueryの機能 はUnix Timestampで書 く必要 があり、実質 手 で書 くのは不可能 なものもありましたが、自動 変換 により救 われる) 結果 セットをローカル時間 に自動 変換 (基本 的 にUTCで帰 ってくるので、ローカル時間 で考 える際 に+9時間 しなきゃいけなかったりしますが、C#側 でデシリアライズする際 にローカルタイムに自動 変換 する)全 てが型付 きで入力 補完 が全面 的 に効 く全 てのBigQuery関数 の入力 補完 にドキュメント付 き
があって(この
Excel統合
そう、DumpToExcel()で
入 れ方
ExplorerのAdd Connection→View More Drivers からLINQ to BigQueryを
かなり
using static
BigQueryの
これにより、クエリを
How to make LINQPad Driver
ちなみに
まとめ
デスクトップGUIクライアントの
同期 (風 )コードと対比 させたUnity+UniRxで非同期 を扱 う場合 のパターン集
- 2015-10-23
UniRxのGitHubのStar
さて、
public void Sync()
{
/* before action */
Method();
/* after action */
}
public IEnumerator IEnumerator()
{
/* before action */
yield return StartCoroutine(Method());
/* after action */
}
public async Task Task()
{
/* before action */
await MethodAsync();
/* after action */
}
みたいな
非同期 汚染
コード
もちろん、
// 次期 バージョンに入 るので、それまでの代用 ということで。
// 元 シーケンスが非同期 なら .Select(x => { /* action(); */ return Unit.Default; }) とほぼ同様
namespace UniRx
{
public static class UniRxExtensions
{
public static IObservable<Unit> ForEachAsync<T>(this IObservable<T> source, Action<T> onNext)
{
return Observable.Create<Unit>(observer =>
{
return source.Subscribe(x =>
{
try
{
onNext(x);
}
catch (Exception ex)
{
observer.OnError(ex);
return;
}
}, observer.OnError, () =>
{
observer.OnNext(Unit.Default);
observer.OnCompleted();
});
});
}
}
}
また、
戻 り値 のない場合
public async Task Demo1_TaskAsync()
{
/* before action */
var x = await Task.Factory.StartNew(() => 100);
/* after action */
}
public IObservable<Unit> Demo1_IOAsync()
{
/* before action */
return Observable.Start(() => 100)
.ForEachAsync(_ =>
{
/* after action */
});
}
メソッドに
内部 に複数 の非同期 がある場合
public async Task Demo2_TaskAsync()
{
/* before action */
var x = await Task.Factory.StartNew(() => 100);
/* after action 1 */
var y = await Task.Factory.StartNew(() => 200);
/* after action 2 */
}
public IObservable<Unit> Demo2_IO_1Async()
{
/* before action */
return Observable.Start(() => 100)
.SelectMany(x =>
{
/* after action 1 */
return Observable.Start(() => 200);
})
.ForEachAsync(y =>
{
/* after action 2 */
});
}
awaitの
パイプライン中 に複数 の値 を伝搬 したい場合
public IObservable<Unit> Demo2_IO_2Async()
{
/* before action */
return Observable.Start(() => 100)
.SelectMany(x =>
{
/* after action 1 */
return Observable.Start(() => 200);
}, (x, y) => new { x, y }) // transport argument to next chain
.ForEachAsync(o =>
{
/* after action 2 */
// { o.x, o,y }
});
}
public IObservable<Unit> Demo2_IO_2_2Async()
{
/* before action */
return Observable.Start(() => 100)
.SelectMany(x =>
{
/* after action 1 */
var z = SyncMethod();
return Observable.Start(() => 200).Select(y => new { x, y, z });
})
.ForEachAsync(o =>
{
/* after action 2 */
// { o.x, o,y, o.z }
});
}
非同期 が連鎖 する場合
public IObservable<Unit> Demo2_IO_2_MoreChainAsync()
{
/* before action */
return Observable.Start(() => 100)
.SelectMany(x =>
{
/* after action 1 */
return Observable.Start(() => 200);
}, (x, y) => new { x, y })
.SelectMany(o =>
{
/* after action 2 */
return Observable.Start(() => 300);
}, (o, z) => new { o.x, o.y, z }) // re-construct self
.ForEachAsync(o =>
{
/* after action 3 */
// { o.x, o,y, o.z }
});
}
SelectManyの
戻 り値 を返 す場合
public async Task<int> Demo3_TaskAsync()
{
/* before action */
var x = await Task.Factory.StartNew(() => 100);
/* after action */
return x; // return value
}
public IObservable<int> Demo3_IOAsync()
{
/* before action */
return Observable.Start(() => 100)
.Select(x =>
{
/* after action */
return x; // return value
});
}
ForEachAsyncではなく、Selectを
例外 をキャッチ
public async Task Demo4_TaskAsync()
{
/* before action */
try
{
var x = await Task.Factory.StartNew(() => 100);
}
catch (Exception ex)
{
/* onerror action */
throw;
}
/* after action */
}
public IObservable<Unit> Demo4_IOAsync()
{
/* before action */
return Observable.Start(() => 100)
.Catch((Exception ex) =>
{
/* onerror action */
return Observable.Throw<int>(ex);
})
.ForEachAsync(x =>
{
/* after action */
});
}
これはCatchで
Finally
public async Task Demo5_TaskAsync()
{
/* before action(1) */
try
{
var x = await Task.Factory.StartNew(() => 100);
}
finally
{
/* finally action(2) */
}
/* after action(3) */
}
// not equivant try-finally
public IObservable<Unit> Demo5_IO_PseudoAsync()
{
/* before action(1) */
return Observable.Start(() => 100)
.Finally(() =>
{
/* finally action(3) */
})
.ForEachAsync(x =>
{
/* after action(2) */
});
}
public IObservable<Unit> Demo5_IO_CorrectLightweightButIsNotDryAsync()
{
/* before action(1) */
return Observable.Start(() => 100)
.Do(_ => { /* finally action(2) */}, _ => {/* same finally action(2) */})
.ForEachAsync(x =>
{
/* after action(3) */
});
}
Finallyに
並列 処理
public async Task ParallelAsync()
{
var a = Task.Factory.StartNew(() => 100);
var b = Task.Factory.StartNew(() => 200);
var c = Task.Factory.StartNew(() => 300);
var xs = await Task.WhenAll(a, b, c);
/* after action */
}
public IObservable<Unit> ParallelIO()
{
var a = Observable.Start(() => 100);
var b = Observable.Start(() => 200);
var c = Observable.Start(() => 300);
return Observable.WhenAll(a, b, c)
.ForEachAsync(xs =>
{
/* after action */
});
}
タイムアウト
public async Task TimeoutAsync(TimeSpan timeout)
{
var task = Task.Factory.StartNew(() => 100);
var delay = Task.Delay(timeout);
if (await Task.WhenAny(task, delay) == delay)
{
/* timeout action */
throw new TimeoutException();
}
/* after action */
}
public IObservable<Unit> TimeoutIO(TimeSpan timeout)
{
return Observable.Start(() => 100)
.Timeout(timeout)
.Catch((TimeoutException ex) =>
{
/* timeout action */
return Observable.Throw<int>(ex);
})
.ForEachAsync(x =>
{
/* after action */
});
}
タイマウトも
IEnumeratorに戻 す
public IObservable<Unit> Demo6_IE()
{
/* before action(1) */
return Observable.FromCoroutine(() => Demo6_IECore());
}
IEnumerator Demo6_IECore()
{
// 戻 り値 の不要 な場合
yield return Observable.Start(() => 100).StartAsCoroutine();
int ret;
yield return Observable.Start(() => 100).StartAsCoroutine(x => ret = x);
}
SelectManyの
だったらもはや
async/awaitは必要 ?
みたとーり、