Model#1 - 该模型位于Dev Server的数据库中。 Model #1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png
模型#2 - 该模型位于我们的Prod服务器上的数据库中,并且每天通过自动提要进行更新。 alt text http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png
我已经编写了一些简单的代码来将我的Feed(Model#2)同步到我的工作DB(Model#1)中。请注意这是原型代码,模型可能不如它们应该的那么漂亮。此外,进入链接数据(主要是ClientID)的模型#1是一个手动过程,这就是我编写这个简单同步方法的原因。
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;
}
}
}
}
现在提出问题:
TIA
答案 0 :(得分:2)
1)您看到null
source.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)您可能遇到的一个问题是请求Products或AutoNegotiationContacts可能生成的数据库查询数。作为替代方案,请考虑批量加载它们或在初始查询中使用join
。
将对象上下文用于一个“操作”,然后处理它,而不是将它们跨请求持久化也被视为一种良好的做法。初始化一个开销非常小,因此每个SychFeeds()
一个对象上下文更合适。 ObjectContext
实现IDisposable
,因此您可以在using
块中对其进行实例化,并将方法的内容包装在其中,以确保在提交更改后所有内容都得到正确清理。