- 1 :デフォルトの名無しさん:2008/02/09(土) 23:51:34
- VisualStudio2008より追加された便利で強力な機能
統合言語クエリ (LINQ : Language Integrated Query)
ちょっと使ってみると、意外と難しいし、テクニック的にも奥が深いものです。
関数型言語にしかないような機能ラムダ式(Lambda式)などはオブジェクト指向とは一味違う機能です。
DataBaseの操作にも、Xmlの操作にも、さらにもっと単純な配列なコンテナにさえ機能する
言語共通・高汎用な統合言語クエリを皆で一緒にマターリ勉強しましょう。
質問、便利なマイテクニックの発表、いろいろやっちゃってください。 - 2 :デフォルトの名無しさん:2008/02/09(土) 23:52:34
- >>1 もこれから使い始めます、答えられそうな質問にはどんどん答えます、無理なのは……誰かお願い。
- 3 :デフォルトの名無しさん:2008/02/10(日) 00:05:21
- まずは一発目
LINQってなあに、という所で、これは以下のような事ができます。
このコードは配列から4以下の値を取り出します。
int [] data = new int[] { 3, 1, 4, 1, 5, 9, 2, 6 };
IEnumerable<int> x = from s in data where s <= 4 select s;
foreach (int ite in x)
System.Console.Write( "{0}," , ite);
3,1,4,1,2,
これを、ちょっと短くしてみる。
int [] data = new int[] { 3, 1, 4, 1, 5, 9, 2, 6 };
foreach (int ite in from s in data where s <= 4 select s)
System.Console.Write( "{0}," , ite);
とてもすっきりかけます。 - 4 :デフォルトの名無しさん:2008/02/10(日) 00:20:06
- 部分的にSQLがかけますよ、って感じか
どーなんだろ、便利か?これ - 10 :デフォルトの名無しさん:2008/02/10(日) 07:20:46
- 何が便利かって、グループ化の機能が便利だ。
- 12 :デフォルトの名無しさん:2008/02/11(月) 15:15:26
- データベースからデータを拾ってきて、LocationID が 10 未満の行を取り出すサンプル。
従来コードから徐々に LINQ に書き換えて行って見ました。
データは、Microsoft SQL Server 2005 に最初から入っているものです。
こちらの使用環境は Professional エデッションで、二枚付いているディスクはフルインストール
ウインドウズ認証でインストールして特に変わった設定がしてなければ、"貴方のPC" を自分のPC名に書き換えれば動くと思います、多分。
データベースは、最初から入っているサンプルデータ AdventureWorks の中の Location(Production) を使ってみました。
DataGridView コントロールを二つ貼り付けて、ボタンを一つ用意して、ボタンプッシュのイベントで実行しています。 - 35 :デフォルトの名無しさん:2008/02/15(金) 10:20:31
- DBを使わなくてもLINQは便利なんだよ~!ってことを布教するためw、
普通のコレクションに対してロジックを実行するクエリのサンプルを示してみます。
>>10が言うように、グループ化の処理をクエリ一発で書けるのは実に魅力的です。
ファイル名を格納したstring配列 files に対して処理を行います。
// 拡張子ごとにファイル名をグループ化するクエリ
var extGroupQuery = from filename in files
let ext = System.IO.Path.GetExtension(filename).ToLower()
group filename by ext into extGroup
select extGroup;
// グループ化したクエリは2重のIEnumerable<T>になってます
foreach (var extGroup in extGroupQuery)
{
Console.WriteLine("Extension: {0}, Count: {1}", extGroup.Key, extGroup.Count());
foreach (var filename in extGroup)
{
Console.WriteLine("\t{0}", filename);
}
} - 53 :デフォルトの名無しさん:2008/02/16(土) 17:54:00
- Q.表を結合したい3(非等価結合、やや使う違いない)
let を使って、選択した行を保持する事により実現できます。
class 得点表 { public string 氏名 { set; get; } public int 得点 { set; get; } }
class 評価表 { public int 以上 { set; get; } public int 未満 { set; get; } public string 評価 { set; get; } }
class 氏名と評価 { public string 氏名 { set; get; } public string 評価 { set; get; } }
var tableOrg1 = new 得点表[] {
new 得点表() { 氏名="Aさん" , 得点=10 },
new 得点表() { 氏名="Bさん" , 得点=100 },
new 得点表() { 氏名="Cさん" , 得点=60 },
};
var tableOrg2 = new 評価表[] {
new 評価表() { 以上=0 , 未満=20, 評価="丙" },
new 評価表() { 以上=20 , 未満=70, 評価="乙" },
new 評価表() { 以上=70 , 未満=101, 評価="甲" },
};
var table1 = from row1 in tableOrg1
let selectLines = from row2 in tableOrg2 where (row2.以上 <= row1.得点 && row1.得点 < row2.未満) select row2
select new 氏名と評価() { 氏名 = row1.氏名, 評価 = selectLines.First().評価 };
table1 の結果
Aさん 丙
Bさん 甲
Cさん 乙
あんま綺麗じゃない……equalsに対してLINQの拡張求む > Microsoft - 85 :デフォルトの名無しさん:2008/02/20(水) 23:37:59
- ( ゜д゜)ノ ハイ!シツモーン!です。
次のように追加してくと実行時間がリニアに増えてくんだけど何か間違えてるんでしょうか?
プロジェクトごとあげてみました。
http://www.borujoa.org/upload/source/upload16875.zip
class Program {
static void Main(string[] args) {
var db =new TestDB(@"testDB.sdf");
db.DeleteDatabase();
db.CreateDatabase();
var count=0;
var tu=new TickUtil();
tu.WriteLine("begin--");
while(count++<5000){
var person=new Person{Name=string.Format("name-{0:8d}",count),
Age=count,Explanation=string.Format("Explain-{0}",count)};
db.Persons.InsertOnSubmit(person);
db.SubmitChanges();
if(count%100==0)
tu.WriteLine("new person-count={0}",count);
}
tu.WriteLine("end-");
}
} - 92 :デフォルトの名無しさん:2008/02/22(金) 00:11:14
- >>1 です
クエリ式はとりあえず放って置いて、メソッドでしか表現できないタイプのものを解説してみようと思っているのですが
まずは一発目で Aggregate あたりからやってみようかと思ってます。
ただ、このメソッドあまりにも関数型言語らしい仕様をしています。
何か良い説明方法はないかと色々さがしているのですが、良いのがあったら誰か紹介してください。
http://d.hatena.ne.jp/blanketsky/20071129/1196329379
とりあえず、この辺りとか見てみたのですが……
こんなの見せられたら初心者さん気絶するよなとか思いつつ、何かいいのはないかなと…… - 188 :デフォルトの名無しさん:2008/07/07(月) 22:53:07
- 書いてみろ
- 197 :デフォルトの名無しさん:2008/07/19(土) 20:38:17
- マイクロソフト公式解説書としてLINQ本が出るってよ
LINQテクノロジ入門
http://ec.nikkeibp.co.jp/item/books/A04100.html
・07/22発売 3,360円(税込み) B5変 280P - 261 :デフォルトの名無しさん:2008/10/27(月) 22:22:31
- Enumerableにある関数は、全部使い込みましょう、特に重要なのは
シーケンスを混ぜて一つのシーケンスを作る系
Enumerable.Concat()
Enumerable.Intersect()
Enumerable.Union()
Enumerable.Except()
シーケンスの先頭や部分を取得する系
Enumerable.First()
Enumerable.FirstOrDefault()
Enumerable.Take()
Enumerable.Skip()
全シーケンスのチェック、これ以上複雑な物は foreach の方がかえって分かりやすい気がする。
Enumerable.All()
Enumerable.Any()
Enumerable.SequenceEqual()
要素の型変換、指定型のみ抽出
Enumerable.Cast()
Enumerable.OfType()
マニュアルが余りに理解不能な文書なので、動作を確かめながら自分の言葉で整理しておくと便利です。
生成用関数、加工用関数、結果生成用関数の三つに分類してみると、すっきりしてきます。 - 262 :デフォルトの名無しさん:2008/10/27(月) 23:24:32
- サンプル通りにやってもAddの定義が無いのですが‥‥
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=46703&forum=7&2
ぶっちゃけ、この常連しんさんと全く同じ質問なのですが、
この人、質問して、自己解決して、回答書いてないので‥‥ - 265 :デフォルトの名無しさん:2008/10/28(火) 03:14:06
- >>261
最も基本の Select, SelectMany が抜けてる
>>262
多分、LINQ to SQLだよな
Add がどこから出てきたのか知らんが、対象がTable<T>なら
データ操作にはInsert~とかDelete~あたりをつかう - 310 :デフォルトの名無しさん:2009/01/04(日) 23:25:17
- 例えば、
Select Sum(col1),Sum(col2),Sum(col3) from Table1
なSQLだとLINQではどう書くの? - 315 :デフォルトの名無しさん:2009/01/07(水) 03:06:42
- var result =
from item in Table1
select new {Sum1 = item.col1.Sum(), Sum2 = item.col2.Sum(), Sum3 = item.col3.Sum(), }
でいいんじゃね? - 316 :デフォルトの名無しさん:2009/01/07(水) 04:16:09
- いや、良くない。範囲変数itemは単なる1レコードで、item.col?はスカラー
1回のループで計算したいなら、アキュムレータ使うしかないはず
var sum = Table1.Aggregate(new[] { 0, 0, 0 }, (y, x) => {
y[0] += x.col1;
y[1] += x.col2;
y[2] += x.col3;
return y;
}); - 317 :デフォルトの名無しさん:2009/01/07(水) 05:35:25
- >>316
それはクエリプロバイダ次第じゃなかろうか。
確かにLINQ to Objectのみなら>>316の書き方の方が速い。
しかしTable1.Aggregateのオーバーロード解決次第によっては
クエリプロバイダの提供する最適なクエリ演算子ではなく
LINQ to Objectの低速なパスで実行されるため>>316はかえって遅くなる。
式木的に
Select Sum(col1),Sum(col2),Sum(col3) from Table1
というSQLに対応するのが何かと聞かれれば>>315を推したい。
あとは>>310が何を期待して聞いたか次第かな。
LINQ to SQLでの書き方を期待していたなら>>315でも最適化されたと思うが。 - 354 :デフォルトの名無しさん:2009/05/21(木) 22:07:37
- パイナップルと酢豚みたいなもんだな
- 406 :デフォルトの名無しさん:2009/07/16(木) 00:20:28
- C#なら拡張メソッドがんがん作ってそういうのをチェックしながらのWhereとか例外メッセージつきのSelectとかいろいろ作りゃいいんじゃねーの。
0スタートのindexがくっついてくるSelectWithCountとか自分的に便利。 - 407 :デフォルトの名無しさん:2009/07/16(木) 04:16:14
- >>406
それって標準のと何が違うの?
http://msdn.microsoft.com/ja-jp/library/bb534869.aspx - 410 :デフォルトの名無しさん:2009/07/16(木) 10:22:56
- 引数なしのAny()とかも影薄いよな
Count() > 0とかやっちゃってる人も多そう - 411 :デフォルトの名無しさん:2009/07/16(木) 14:36:23
- 作ってみると意外と簡単でつい自前で作ってしまう。
デバッグ用に意外と役に立ったり。
public??static??void??ToVoid<T>(this??IEnumerable<T>??src)??{
????foreach??(var??s??in??src)??{};
}
public??static??void??ToVoid<T>(this??IEnumerable<T>??src,??Action<T>??act)??{
??foreach??(var??s??in??src)??act(s);
} - 422 :デフォルトの名無しさん:2009/09/14(月) 21:12:59
- static IEnumerable<IEnumerable<TSource>> Slice<TSource>(this IEnumerable<TSource> source, int n)
{
var buf = new TSource[n];
int i = 0;
foreach (var item in source) { buf[i++] = item; if (i == n) { i = 0; yield return buf; } }
if (i != 0) { yield return buf.Take(i); }
} - 432 :デフォルトの名無しさん:2009/09/27(日) 19:20:03
- 条件に合うものと合わないものを分けるために、
bar = foo.Select(i=>Baz(i) );
foo = foo.Select(i=>!Baz(i));
みたいに2回Selectしてるんですが、
1回で済む方法ないですか? - 446 :デフォルトの名無しさん:2009/10/13(火) 19:08:08
- LINQ to SQLって、要するに式ツリーからSQLを生成するORMという理解でOK?
- 460 :デフォルトの名無しさん:2009/11/15(日) 02:05:16
- SelectMany の戻り値に一つだけ要素を足したいです。
今は、
var list = new List<T>();
list.Add(item);
list.AddRange(foo.SelectMany(i => bar(i)));
のように書いてますが、なんか
冗長な気がします。
1個要素を足すためだけに List のインスタンスを
生成するのは無駄な気がするんですが、
避ける方法ないでしょうか? - 461 :460:2009/11/15(日) 02:16:19
- すまん、Concat を見つけた。
foo.SelectMany(i=>bar(i)).Concat(new[]{ item });
と書けた。
でも、配列生成してんのが無駄な気がするが、
回避する方法ないよね?
( new List<T>(){ item } とかは無しでw) - 464 :デフォルトの名無しさん:2009/11/15(日) 11:46:45
- >>461
Enumerable.Repeat(item, 1) で回避。 - 469 :デフォルトの名無しさん:2009/12/11(金) 00:11:22
- Linq to Object で List 内のデータを取り出した時に、そのデータを変更することはできるのでしょうか?
Linq to Object では、抽出するだけなのでしょうか? - 472 :デフォルトの名無しさん:2009/12/12(土) 14:18:30
- ちなみに、標準では Foreach メソッドみたいなのないけど、
それを認めると LINQ 中で副作用起こすのを推奨しちゃうことになるから避けたらしい。
list.Select(x => xxx).Foreach(x => x.Property = xxx);
みたいなのは邪道。
LINQ 中では副作用は起こさないこと推奨。 - 477 :デフォルトの名無しさん:2009/12/12(土) 18:50:51
- Linqというよりそこで使われてる静的クロージャの問題。
.NET2.0でクロージャが実装されたとき有名になったプログラム。
i,??j がどんな値になるか想像つく?
using??System;
using??System.Collections.Generic;
delegate??void??F();
class??Test??{
????static??void??Main()??{
????????List<F>??actionList??=??new??List<F>();??
????????for(int??i??=??0;??i??<??10;??++i)??{
????????????int??j??=??i;
????????actionList.Add(delegate(){Console.WriteLine("i={0},??j={1}",i,??j);});??
????????}
????????foreach??(F??f??in??actionList)??f();
????}
} - 524 :デフォルトの名無しさん:2010/02/14(日) 00:25:34
- IEnumerable に ForEach がないのは何でなんだろ
- 546 :デフォルトの名無しさん:2010/06/06(日) 10:17:56
- その二つはVB使いには使い方が理解しづらいメソッドの定番
LINQも同様に高階関数使ってるけどクエリ式で隠してるわけだ - 550 :デフォルトの名無しさん:2010/06/10(木) 07:41:28
- C#, EF4で、ちょっとハマったので質問させてくれ。
DbContextというのがedmxで定義されたコンテキスト、Hogeというのがedmxで定義されたエンティティ型で、
Piyoがedmxとは関係ないクラスだとする。
「DbContext.Hoge.Select(x => new Piyo() { A = x.A, B = x.B })」
みたいな書き方は普通にできて、普通にIQueriable<Piyo>(実体はObjectQuery<Piyo>)が返ってくるよね。
CreateQueryを使って同じようなことがしたいとき(つまりObjectQuery<Piyo>がほしいとき)
どうすればいいんだろう?
「DbContext.CreateQuery<Piyo>("SELECT VALUE Piyo (x.A, x.B) FROM Hoge AS x")」
こう書くと、「Piyoなんて型見つからない」って怒られるし、かといってE-SQL内でVALUE Piyoを
指定しないと「MaterializedDataRecordからPiyoに変換できない」と怒られるし(当然だけど)。 - 559 :デフォルトの名無しさん:2010/06/24(木) 04:14:11
- 比較する際に内部では、最初にGetHashCodeでハッシュコードを取得して、
それが同じ値であったらEqualsで比較する、という動きをします。
なので、GetHashCodeはobj.FullName.GetHashCode()だけ返せばいいんじゃないのかな?
LastWriteTimeまで算出に含めるから希望通りに動かないのでは、と思ってみる。
あと、FullNameじゃそもそも「ファイル名」じゃなくてフルパスを取っちゃうから絶対に一致しない。
でも、なんというか、その用途にExceptは違う気もします。 - 570 :デフォルトの名無しさん:2010/12/14(火) 07:21:36
- ORマッパーになると聞いたが
具体的にどんなふうになるのん? - 571 :デフォルトの名無しさん:2010/12/14(火) 20:57:11
- >>570
1.エンティティを定義
[Table]
public class Table1
{
[Column(IsPrimaryKey=true)]
pubic int Key{ get; set; }
[Column]
pubic string Column2{ get; set; }
[Column]
pubic string Column3{ get; set; }
}
2.DataContextを定義
public TestContext :DataContext
{
public TestContext (string connectionString):base(connectionString){}
public Table<Table1> Table1;
}
2. DataContextをインスタンス化してLINQでアクセス
var dc = new TestContext (接続文字列);
var list = dc.Table1.Where(row=>row.Column2=="test").OrderBy(row=>row.Column2).ToList(); - 578 :デフォルトの名無しさん:2011/01/27(木) 16:14:48
- ちょっと困ってるので質問
TableA:
Key1 string
Key2 string
TableB:
Key1 string
Key2 string
Key3 int
この2つのTableをleft joinさせる
var q=from n in TableA join m in TableB on new {n.Key1,n.Key2} equals new {m.Key1,m.Key2} into z
from a in z.DefaultIfEmpty()
select new {n.Key1,n.Key2,a.Key3};
そうするとforeachの段階で「a.Key3がnull許容型じゃない」と怒られる
複合キーだからnull許容には出来ないし、そもそもDefaultIfEmpty()って値型はデフォルトの値入れてくれるんじゃないのかと
これってどうすれば? - 581 :デフォルトの名無しさん:2011/01/27(木) 23:57:21
- [TableA]
Key1 Key2
hoge fuga
foo bar
[TableB]
Key1 Key2 Key3
hoge fuga 1
[Result]
Key1 Key2 Key3
hoge fuga 1
foo bar NULL - 582 :581:2011/01/28(金) 00:04:25
- 途中で送ってしもた
例えばDB上でTableA,Bが上記のような場合、LEFT JOINしたらResultのようになるが、
これを(string, string, int)に入れようとすればエラーになって当然
とりあえず、匿名クラスを(string, string, int?)にすれば良い - 583 :578:2011/01/28(金) 14:49:37
- >>582
ありがとうございます
ところでselect匿名型で型指定するにはどう書けば良いでしょうか? - 591 :デフォルトの名無しさん:2011/03/25(金) 21:52:20.02
- LINQは禁止だけどDataTable.SelectはOKって意味が分からんよな
- 602 :デフォルトの名無しさん:2011/03/27(日) 12:25:59.03
- 理由は間違ってるがその規約自体は必ずしも間違ってないぞ
privateやinternalならいいが、アセンブリの外から見えるconst定数は
バージョン管理上問題があるので非推奨 - 635 :デフォルトの名無しさん:2011/06/28(火) 13:00:23.68
- 複数のテーブルが複数のsdf(SQL Server Compact)ファイルに分散して格納されています。
#テーブル1,2はファイル1、テーブル3,4,5はファイル2など。
このような場合でもLinq to Entitiesで全てのテーブルを連携した検索等を行うことは可能でしょうか?
Linq自体これから勉強するところなのですが、仕様を先に決めなければなりません。
ご教示よろしくお願いします。 - 636 :デフォルトの名無しさん:2011/06/28(火) 13:09:40.13
- >>635
コードの見た目上は連携したように見えるものは書けると思うけど、
sdf ファイルごとにそれぞれ個別のクエリが動くと思う。 - 668 :デフォルトの名無しさん:2011/07/20(水) 02:11:33.40
- LINQ始めたてでよくわかってないんですが、C#の場合
var q = array.Where(x => x <= 4).Select(x => x);
配列から4以下の数値を、取り出す文の場合なんでWhereとSelectの中になんでラムダ式が入っているんですか?
それとxという変数っぽいのはなんなんですか? - 708 :デフォルトの名無しさん:2012/02/24(金) 22:06:01.26
- アイドルが同じ名前を使ってるけど、
これって、商標権的にどうなの?
http://ja.wikipedia.org/wiki/LinQ - 724 :デフォルトの名無しさん:2012/06/27(水) 11:03:37.78
- サーバー一緒か?
いずれにしてもクエリーフックしてどう違うかみて、そのクエリーを単体でやったらどうなるかとかより切り分けれ
http://toro.2ch.net/test/read.cgi/tech/1202568694/l50/../人気ブログランキングへ