2010-01-20 42 views
1

模型1 - 此模型位于开发服务器上的数据库中。 Model #1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.pngC# - 实体框架 - 了解一些基本知识

Model#2 - 此模型位于Prod服务器的数据库中,并且每天都通过自动提要进行更新。 alt text http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

我已经写了什么应该是一些简单的代码来同步我的饲料(模型#2)到我的工作数据库(模型#1)。请注意,这是原型代码,模型可能不像应该那样漂亮。此外,进入链接数据模型#1(主要是ClientID)是一个手动过程,这就是为什么我写这个简单的同步方法。

private void SyncFeeds() 
{ 
    var sourceList = from a in _dbFeed.Auto where a.Active == true select a; 
    foreach (RivWorks.Model.NegotiationAutos.Auto source in sourceList) 
    { 
     var targetList = from a in _dbRiv.Product where a.alternateProductID == source.AutoID select a; 
     if (targetList.Count() > 0) 
     { 
      // UPDATE... 
      try 
      { 
       var product = targetList.First(); 
       product.alternateProductID = source.AutoID; 
       product.isFromFeed = true; 
       product.isDeleted = false; 
       product.SKU = source.StockNumber; 
       _dbRiv.SaveChanges(); 
      } 
      catch (Exception ex) 
      { 
       string m = ex.Message; 
      } 
     } 
     else 
     { 
      // INSERT... 
      try 
      { 
       long clientID = source.Client.ClientID; 
       var companyDetail = (from a in _dbRiv.AutoNegotiationDetails where a.ClientID == clientID select a).First(); 
       var company = companyDetail.Company; 
       switch (companyDetail.FeedSourceTable.ToUpper()) 
       { 
        case "AUTO": 
         var product = new RivWorks.Model.Negotiation.Product(); 
         product.alternateProductID = source.AutoID; 
         product.isFromFeed = true; 
         product.isDeleted = false; 
         product.SKU = source.StockNumber; 
         company.Product.Add(product); 
         break; 
       } 
       _dbRiv.SaveChanges(); 
      } 
      catch (Exception ex) 
      { 
       string m = ex.Message; 
      } 
     } 
    } 
} 

现在的问题:

  1. 在型号#2,对于汽车类结构缺少客户端ID(见红色圆圈区域)。现在,我学到的一切,EF创建了一个子类的Client,我应该能够在子类中找到ClientID。然而,当我运行我的代码时,source.Client是一个NULL对象。我期待EF不能做什么?有没有一种方法来正确填充子类?
  2. 为什么EF在父表中隐藏子实体ID(在这种情况下是ClientID)?有什么方法可以揭露它吗?
  3. 还有什么像谚语疼拇指伸出?

TIA

+0

对不起您的损失。 [Linkrot](http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png)是生活的一部分。对我们的数字化历史构成巨大威胁。 – 3yanlis1bos 2013-03-07 13:15:17

回答

2

1)你看到一个nullsource.Client的原因是因为相关对象不加载,直到你要求他们,或者他们正在以其他方式加载到对象上下文。下面将显式地加载它们:

if (!source.ClientReference.IsLoaded) 
{ 
    source.ClientReference.Load(); 
} 

然而,这是次优的,当你有一个以上的记录列表,因为它每Load()电话发送一个数据库查询。更好的选择是对Include()方法在初始查询,指示ORM加载相关实体您有兴趣,所以:

var sourceList = from a in _dbFeed.Auto .Include("Client") where a.Active == true select a; 

另一种第三种方法是使用的东西的调用关系的修复行动,例如,在你的例子中,如果相关的客户端先前被查询过,他们仍然会在你的对象上下文中。例如:

var clients = (from a in _dbFeed.Client select a).ToList(); 

的EF然后将“固定式”所谓source.Client关系不会null。很显然,这只是在你要求所有客户端进行同步列表时才会做的事情,因此与您的具体示例无关。

请务必记住,除非您请求对象,否则永远不会将对象加载到EF中!

2) EF的第一个版本故意不将外键字段映射到可观察的字段或属性。 This是关于此事的一个很好的概要。在EF4.0中,我知道外键会因受欢迎的需求而暴露出来。

3)您可能遇到的一个问题是请求产品或AutoNegotiationContacts可能产生的数据库查询的数量。作为替代方案,请考虑在初始查询中批量加载它们或使用join加载它们。

对一个'操作'使用对象上下文,然后将其处理掉,而不是跨请求持久化它也被认为是好的做法。初始化开销很小,因此每个SychFeeds()更合适一个对象上下文。 ObjectContext实现了IDisposable,所以你可以在using块中实例化它,并在其中包含方法的内容,以确保提交更改后,所有内容都可以正确清理。

+0

感谢您的反馈。要记住这么多好的做法并巩固到位。到目前为止,我喜欢EF比ADO.NET好得多 - 尽管涉及到学习曲线的成本。但是 - 我**爱**学习! – 2010-01-20 23:33:08

+0

另一个说明:上下文是在整个班级的入口点创建的。该类被实例化,调用一个方法,然后该类被禁用,因为它是没有会话状态的Web服务的一部分。我正在研究如何在这种情况下使用using子句。我在班级的申报区域申报我的背景。每个Web服务方法实例化这个类,调用一个方法,然后在退出该方法时清空该类。 (有意义吗?) – 2010-01-20 23:36:13

+0

如果类的全部目的是针对一种方法,那么您可以将方法内容包装在using语句中,例如 私人无效SynchFeed(){ 使用 (YourContext _dbRiv =新YourContext()){ // 做工作 }} 这是假设,因为我认为你所说的那样,上下文(或类)除了SynchFeed()之外什么都不做。我对使用Web服务并不熟悉,所以如果这不可行,我的道歉。 在这种情况下,这不是什么大问题 - 当您在多个操作(即对SyncFeed()的很多调用)中保持上下文活动时,您应该真正考虑重构。 – 2010-01-20 23:59:57