C#-实体框架-了解一些基础知识
模型#1-此模型位于开发服务器上的数据库中。 模型#2-此模型位于Prod服务器上的数据库中,并通过自动提要每天更新 我已经编写了一些简单的代码,将提要(Model#2)同步到我的工作数据库(Model#1)中。请注意,这是原型代码,模型可能没有它们应有的漂亮。此外,在这一点上,feed link数据(主要是ClientID)的Model#1输入是一个手动过程,这就是我编写这个简单同步方法的原因C#-实体框架-了解一些基础知识,c#,.net,entity-framework,models,C#,.net,Entity Framework,Models,模型#1-此模型位于开发服务器上的数据库中。 模型#2-此模型位于Prod服务器上的数据库中,并通过自动提要每天更新 我已经编写了一些简单的代码,将提要(Model#2)同步到我的工作数据库(Model#1)中。请注意,这是原型代码,模型可能没有它们应有的漂亮。此外,在这一点上,feed link数据(主要是ClientID)的Model#1输入是一个手动过程,这就是我编写这个简单同步方法的原因 private void SyncFeeds() { var sourceList = f
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;
}
}
}
}
现在回答问题:
源.客户端的为null
的原因是相关对象在您请求之前未加载,或者它们已加载到对象上下文中。以下内容将显式加载它们:
if (!source.ClientReference.IsLoaded)
{
source.ClientReference.Load();
}
但是,当您有一个包含多条记录的列表时,这是次优的,因为它会在每次Load()
调用时发送一个数据库查询。更好的替代方法是使用初始查询中的方法,指示ORM加载您感兴趣的相关实体,因此:
var sourceList = from a in _dbFeed.Auto .Include("Client") where a.Active == true select a;
另一种第三种方法是使用调用关系修复(callrelationship fix-up),例如,在您的示例中,如果以前查询过相关的客户机,那么它们仍然会在您的对象上下文中。例如:
var clients = (from a in _dbFeed.Client select a).ToList();
EF随后将“修复”关系,以便source.Client不会为null
。显然,这只是当您需要同步所有客户端的列表时才会执行的操作,因此与您的特定示例无关
始终记住,除非您请求,否则对象永远不会加载到EF中
2)EF的第一个版本故意不将外键字段映射到可观察字段或属性。这是对这件事的一个很好的概述。在EF4.0中,我了解到外键会因大众需求而暴露
3)您可能遇到的一个问题是请求产品或自动协商联系人可能生成的数据库查询数量。作为另一种选择,请考虑在初始查询中以散装或使用<代码>连接< /代码>加载它们。
将对象上下文用于一个“操作”,然后处理它,而不是跨请求持久化它们,这也被视为一种良好的实践。初始化一个对象的开销很小,因此每个SychFeeds()
一个对象上下文更合适ObjectContext
实现了IDisposable
,因此您可以使用块在中实例化它,并将方法的内容包装在其中,以确保在提交更改后正确清理所有内容。感谢您的反馈。要记住这么多,要落实这么多好的实践。到目前为止,我更喜欢EF而不是ADO.NET——尽管这涉及到学习曲线成本。但是-我喜欢学习!!另一方面:上下文是在整个类的入口点创建的。实例化该类,调用单个方法,然后该类为空,因为它是没有会话状态的Web服务的一部分。我正在研究如何在这种情况下使用using子句。我在类的声明区域声明我的上下文。每个web服务方法实例化该类,调用一个方法,然后在退出该方法时将该类置空。(有意义吗?)如果类的全部目的都是为了一个方法,那么您可以将方法内容包装在using语句中,例如private void SynchFeed(){using(YourContext _dbRiv=new YourContext()){//do work}}这假设,正如我想您已经说过的,上下文(或类)除了SynchFeed()之外什么都不做. 我不太熟悉使用web服务,所以如果这不可行,我很抱歉。在这种情况下,这不是什么大不了的事情,而是当你将上下文保持在多个操作中,即许多调用SycPoFor()时,你应该真正考虑重构。谢谢该类有几个公共方法,如GetProductById(id)、GetProductByCompany(id)、SaveProduct(product)、DeleteProduct(id)等。在每个Get方法中,我调用Private Sync()方法一次,然后执行Get操作。因此,调用顺序如下所示:第三方网页-->我们的Web服务(WS)-->实例化ProductManager(PM)对象(创建上下文)-->执行获取、保存或删除-->如果获取、运行同步-->PM将结果返回给WS-->WS drops PM(上下文结束)-->WS返回-->网站使用数据包。对每个WS-call重复此循环。对于您的丢失,深表歉意。是生活的一部分。对我们的数字历史是一个巨大的威胁。