私はOData(WebAPIとEF)を使用してデータベースを照会しています。そして今私は "マージ" 3つの結果に1つのテーブル。EF複数のテーブルを1つのIQueryableに結合します。
私は3つのテーブルとこのようになりますインターフェイスを、持っている:
public class Authority : IAssociationEntity
{
public string Name { get; set; }
public int AuthorityId { get; set; }
}
public class Company : IAssociationEntity
{
public string Name { get; set; }
public int CompanyId { get; set; }
}
public class Organization : IAssociationEntity
{
public string Name { get; set; }
public int OrganizationId { get; set; }
}
public interface IAssociationEntity
{
string Name { get; set; }
}
あなたがそこに3つのテーブルの間にいくつかの明白な類似点がありますが、いくつかの理由のために、彼らは別々のテーブルに滞在する必要が見ることができるように。私が必要とするのは、ページングを使用して3つすべてを名前で検索し、それらを同じリストにユーザー用に提示することです。
私は1つIQueryable
に3つのテーブルをマージする方法はあり
SELECT TOP 4 a.* FROM
(
SELECT CompanyID, Name from Company WHERE Name = 'Bob'
UNION
SELECT OrganizationID, Name from Organization WHERE Name = 'Bob'
UNION
SELECT AuthorityID, Name from Authority WHERE Name = 'Bob'
) AS a
SQL
で次のようになります何かを探していますか?これらの3つのテーブルをIQueryable<IAssociationEntity>
に結合したいと思います。私は本当にインターフェイス(またはおそらく基本クラス)を使用し、結果をOData実装のIQueryable
として取得する必要があります。このような何かが、それはコンパイルされません:
var query = db.Companies
.Concat(db.Organizations)
.Concat(db.Authorities);
IQueryable<IAssociationEntity> mergedTables = query.Cast<IAssociationEntity>();
// Here is an EXAMPLE usage.
// What I really need is to return the IQuearyable<IAssociationEntity> for my OData.
var result = mergedTables.Where(x => x.Name == "Bob").OrderBy(x => x.Name).Skip(2).Take(10);
そしてODATAコントローラのための私の使用:
public class AssociationController : ODataController
{
[EnableQuery]
public override IQueryable<IAssociationEntity> Get(ODataQueryOptions<IAssociationEntity> q)
{
// return my IQueryable here...
}
}
言うまでもないが、私が作成するときにテーブル全体をメモリに読みたくない、言いたいことをIQueryable
。私は実際にページングを使う必要があります。なぜなら、これらの3つのテーブルのいくつかは何百万もの行を持っているからです。
最終的な解決策は、AS終わった:
var query = db.Companies.Select(x => new AssociationEntity { Name = x.Name })
.Concat(db.Organizations.Select(x => new AssociationEntity { Name = x.Name }))
.Concat(db.Authorities.Select(x => new AssociationEntity { Name = x.Name }));
return query;
そして照会可能に対して実行:
_query.Where(x => x.Name.Contains("M")).OrderBy(x => x.Name).Skip(10).Take(50).ToList();
生成されたSQL:あなただけ行わないのはなぜ
SELECT
[UnionAll2].[C1] AS [C1],
[UnionAll2].[Name] AS [C2]
FROM (SELECT
1 AS [C1],
[Extent1].[Name] AS [Name]
FROM [dbo].[Company] AS [Extent1]
WHERE [Extent1].[Name] LIKE N'%M%'
UNION ALL
SELECT
1 AS [C1],
[Extent2].[Name] AS [Name]
FROM [dbo].[Organization] AS [Extent2]
WHERE [Extent2].[Name] LIKE N'%M%'
UNION ALL
SELECT
1 AS [C1],
[Extent3].[Name] AS [Name]
FROM [dbo].[Authority] AS [Extent3]
WHERE [Extent3].[Name] LIKE N'%M%') AS [UnionAll2]
ORDER BY [UnionAll2].[Name] ASC
OFFSET 10 ROWS FETCH NEXT 50 ROWS ONLY
心に来る最初の事は結果を、その後、個別に3つのすべてを照会マージすることです。ページング、順序付けなど、それはどのように複数のテーブルにまたがって行われますか? – Daniel
あなたはなぜこの違いがあるのか教えてください: 'WHERE Name LIKE '%Bob%''は一箇所に、他の場所は 'Where(x => x.Name ==" Bob ")'なぜですか? – Sampath
@Sampath - 良いキャッチ!これは、SQL出力の可能性の例であり、私が実際に行ったことではありません。私は質問を更新しました。 – smoksnes