第二章(7)跨多实体拆分一张表

问题:

  一张表中,有一些字段频繁被使用,而有几个大字段是几乎没被使用过。为了性能考虑,你想避免每次查询的时候都加载这些“消耗昂贵”的字段。这样就需要把一张表分割成两个及以上的实体。

解决过程:

  假设你有这样一张表,如图2-7-1所示。这张表持有照片的信息,同时包括bit级的缩略图和全分辨率的图像。    

图2-7-1

  创建频繁使用字段的实体和包含很少使用的字段实体的步骤如下:

  1. 在工程项目上右键,选择添加“新项”,选择ADO.NET实体数据模型。
  2. 选择“从数据库中生成”,点击“下一步”。
  3. 使用向导选择一个已有数据库连接,或者新建一个。
  4. 在弹出的“选择数据库对象”框中,选择Photograph表,保持最下面的两个复选框选中。点击“完成”。
  5. 在设计界面上右键,选择添加“实体”。在弹出的对话框中,将实体的名字改为“PhotographFullImage”,同时把主键的名字改成PhotoId,这和Photograph实体中的主键名是一样。如图2-7-2所示,点击完成添加新的PhotographFullImage实体类型。
  6. 将HighResolutionBits属性从Photograph实体类型中移到PhotographFullImage实体中。你可以用选择/剪切/粘贴来移动属性。
  7. 点击新创建的PhotographFullImage实体查看它的映射细节。如果映射细节的窗口不可见,在菜单中选择视图-》其他窗口-》实体数据模型映射细节。
  8. 在PhotographFullImage的映射细节窗口,点击添加表或者视图,然后选择Photograph表。将HighResolutionBits列和HighResolutionBIts属性,PhotoId列和PhotoId属性对应起来。如图2-7-3.
  9. 在Photograph实体中右键,选择添加关联(Association)。添加Photograph实体和PhotographFullImage实体之间的一对一关联。确保两件事情:在关联的两个终端的多样性选择了1 和取消选中“添加外键属性”复选框。如图2-7-4.
  10. 在关联上右键,选择“属性”。在约束区域底部的引用约束中,点击按钮添加一个引用约束。将Photograph设为主实体,同时确保主实体和依赖实体的主键属性都设为了PhotoId。如图2-7-5.

图2-7-2

图2-7-3

图2-7-4

图2-7-5

 

    这样完成的模型如图2-7-6所示:

图2-7-6

 

原因:

   Entity Framework并不直接支持单独实体属性的延迟加载的概念。为了得到延迟加载昂贵属性的效果,我们利用了EF支持关联实体延迟加载的功能。也就是创建一个新的实体类型来保存昂贵的全图像属性,然后创建一对一的实体关联。并且在概念层中添加了引用约束,有点像数据库中的引用约束,告诉EF实体PhotographFullImage不能没有Photograph而单独存在。

  也因为引用约束,在我们的模型中有些东西是要注意的。如果我们新建了一个PhotographFullImage实体,那么一个Photograph的实例必须要存在于object context中,或者数据源先调用了savechanges方法。同样,如果我们删除了一个Photograph,那么与之关联的PhotographFullImage也要被删除。这就像数据库中引用约束的级联删除。

    byte[] thumbBits = new byte[100];
    byte[] fullBits = new byte[2000];
    using (var context = new EFRecipesEntities())
    {
        var photo = new Photograph { PhotoId = 1, Title = "My Dog",
        ThumbnailBits = thumbBits };
        var fullImage = new PhotographFullImage { PhotoId = 1,
        HighResolutionBits = fullBits };
        photo.PhotographFullImage = fullImage;
        context.Photographs.AddObject(photo);
        context.SaveChanges();
    }
    using (var context = new EFRecipesEntities())
    {
        foreach (var photo in context.Photographs)
        {
            Console.WriteLine("Photo: {0}, ThumbnailSize {1} bytes",
                             photo.Title, photo.ThumbnailBits.Length.ToString());
            // explicitly load the "expensive" entity, PhotographFullImage
            photo.PhotographFullImageReference.Load();
            Console.WriteLine("Full Image Size: {0} bytes",
                             photo.PhotographFullImage.HighResolutionBits.Length.ToString());
         }
    
    }

 

--------------------------------------------------
Photo: My Dog, Thumbnail Size: 100 bytes
Full Image Size: 2000 bytes
--------------------------------------------------

 

posted @ 2012-10-08 09:55  阿凡迪  阅读(1041)  评论(1编辑  收藏  举报