一:数据库支持
为了演示本例,我们创建了另外一个简单的示例数据库MiniNW,该数据库来自于ADO.NET Entity Framework Extensions,但在本例中,我们不会使用这个针对EF的扩展框架,因为它对POCO的支持不好,同时它也不支持DbContext,简单的说来就是它目前不支持EF4.1。
MiniNW可以在本示例代码的如下位置获得:
数据库对应关系如下(由于数据库相对简单,所以直接列出数据,从数据可以直观看出两表的关系):
二:生成POCO及DbContext
我们使用Entity Framework Power Tools CTP生成POCO及相关映射,如果你对此不熟悉,可参考本篇《使用Entity Framework和WCF Ria Services开发SilverLight之3:Map》。
三:主表从表数据一起关联查询
数据库中存在存储过程GetCategory:
1
2
3
4
5
6
7
8
|
ALTER
proc [dbo].[GetCategory]
@cid
int
as
begin
select
*
from
Categories
where
@cid = cid
end
|
执行此存储过程的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
IEnumerable<Category> GetCategoryWithProductsWithID(
int
id)
{
var parameter =
new
SqlParameter
{
DbType = DbType.Int32,
ParameterName =
"cid"
,
Value = id
};
//联表并延迟加载
var result = (from p
in
this
.Categories.SqlQuery(
"EXECUTE GetCategory @cid"
, parameter) select p).ToList();
return
result;
}
|
得到的数据如下:
其中,Category所对应Products是延迟加载进来的,如果我们只使用Category,数据引擎就不会查询Products表的数据,但是,只要我们一到Category中查看Products,就会获取如上图这样的Products数据。请根据源码中的两个数据实体理解。
执行存储部分的代码EF为我们生成如下:
1
|
exec
sp_executesql N
'EXECUTE GetCategory @cid'
,N
'@cid int'
,@cid=1
|
延迟加载部分的代码EF为我们生成如下:
1
2
3
4
5
6
7
|
exec
sp_executesql N
'SELECT
[Extent1].[pid] AS [pid],
[Extent1].[name] AS [name],
[Extent1].[discontinued_date] AS [discontinued_date],
[Extent1].[cid] AS [cid]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[cid] = @EntityKeyValue1'
,N
'@EntityKeyValue1 int'
,@EntityKeyValue1=1
|
三:仅获取主表数据
如果不需要关联表的数据,我们可以像下面这样编码。以下这段代码使用的是和上文一样的存储过程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
IEnumerable<Category> GetCategoryWithID(
int
id)
{
var parameter =
new
SqlParameter
{
DbType = DbType.Int32,
ParameterName =
"cid"
,
Value = id
};
//非联表
var result = (from p
in
this
.Categories.SqlQuery(
"EXECUTE GetCategory @cid"
, parameter)
select
new
{
cid = p.cid,
name = p.name
}).ToList()
.Select(r =>
new
Category()
{
cid = r.cid,
name = r.name
});
return
result;
}
|
如果你对这段代码表示不很理解,请参看此文《使用Entity Framework和WCF Ria Services开发SilverLight之6:查找指定字段》。
获取数据如下:
四:由从表关联主表数据
从表关联主表的存储过程如下:
1
2
3
4
5
6
7
8
|
ALTER
proc [dbo].[GetProductAndCategory]
@pid
int
as
begin
select
p.pid, p.[
name
] , p.discontinued_date, c.cid, c.[
name
]
from
Products
as
p
join
Categories
as
c
on
p.cid = c.cid
where
p.pid = @pid
end
|
注意,原始例子所带的存储过程不是这样的,多了这样的语句:
DbContext默认支持实体类型的字段和数据库视图是一个字段名,所以我们去掉了重命名部分。
实现此功能的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
IEnumerable<Product> GetProductAndCategoryWithID(
int
id)
{
var parameter =
new
SqlParameter
{
DbType = DbType.Int32,
ParameterName =
"pid"
,
Value = id
};
//延迟加载
var result = (from p
in
this
.Products.SqlQuery(
"EXECUTE dbo.GetProductAndCategory @pid"
, parameter) select p).ToList();
return
result;
}
|
要注意,主表的数据也是延迟加载的,只有使用到的时候才会被查询。
EF为我们生成的代码如下:
1
|
exec
sp_executesql N
'EXECUTE dbo.GetProductAndCategory @pid'
,N
'@pid int'
,@pid=1
|
获取的数据如下: