[英]C#: What is the best way to implement a 'filter' mechanism for ListView Items?
[英]C#, LINQ batch items - what is the best way to do this?
我有2个数据库-(1)供稿,(2)生产。 提要数据库是由我们每天获取的客户端文件提供的,按照我的观点,它是只读的数据源。 收到提要文件后,提要应用程序将执行其操作,然后最终在生产站点上调用Web服务。 然后,此Web服务将在提要DB和Prod DB之间进行同步。 本质上,这是伪代码:
对于分隔插入,更新和删除的核心代码:
List<model.AutoWithImage> feedProductList = _dbFeed.AutoWithImage.Where(feedProduct => feedProduct.ClientID == ClientID).ToList();
List<model.vwCompanyDetails> companyDetailList = _dbRiv.vwCompanyDetails.Where(feedProduct => feedProduct.ClientID == ClientID).ToList();
foreach (model.vwCompanyDetails companyDetail in companyDetailList)
{
List<model.Product> rivProductList = _dbRiv.Product.Include("Company").Where(feedProduct => feedProduct.Company.CompanyId == companyDetail.CompanyId).ToList();
foreach (model.AutoWithImage feedProduct in feedProductList)
{
bool alreadyExists = false;
model.Company company = null;
foreach (model.Product rivProduct in rivProductList)
{
if (feedProduct.StockNumber == rivProduct.SKU)
{
alreadyExists = true;
// Active feed items...
if (feedProduct.Active)
{
// Changed since last sync...
if (feedProduct.Updated > rivProduct.LastFeedUpdate)
{
model.Product updateProduct = new model.Product();
updateProduct.ProductId = rivProduct.ProductId;
// removed for brevity
updateProductList.Add(updateProduct);
}
// Not changed since last sync...
else if (feedProduct.Updated <= rivProduct.LastFeedUpdate)
{
//nop
}
}
// No longer active feed products...
else if (!feedProduct.Active)
{
model.Product deleteProduct = new model.Product();
deleteProduct = rivProduct;
// removed for brevity
deleteProductList.Add(deleteProduct);
}
}
if (company == null)
company = rivProduct.Company;
}
// Found feedProduct new product...
if (!alreadyExists)
{
model.Product insertProduct = new Product();
insertProduct.ProductId = Guid.NewGuid();
// removed for brevity
insertProductList.Add(insertProduct);
}
}
}
是的,我知道有更有效的方法可以做到这一点,并且我正在开始使用它们。 但是,上面的代码可以相对快速地运行,并将我的数据分成3个List <>集。
我的问题更多是关于处理_dbRiv.SaveChanges()方法。 当我发布该文件时, 似乎会触发所有3组(以上)。 我正在尝试查找唯一的键冲突,并且在此过程中我找不到一个或两个违反约束的记录。 我确信我在思考LINQ for SQL的真正工作方式时错过了某些地方。
我想做的是:
是否可以通过某种方式一次对一个批次发出SaveChanges?
有没有办法foreach InsertProductList对象并一次做一次SaveChanges行? 我在树上叫错了吗?
编辑:虽然我知道我可以从EF调用存储的过程,但我的意图是学习如何将存储的过程转换为EF。
我在SQL中写了我想要的东西(这正是我们所需的方式):
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[ExecuteSync] @ClientID AS BIGINT AS
BEGIN
DECLARE @cid UNIQUEIDENTIFIER
DECLARE c1 CURSOR FOR
SELECT CompanyID FROM CompanyDetails WHERE ClientID = @ClientID
OPEN c1
FETCH NEXT FROM c1 INTO @cid
WHILE @@FETCH_STATUS = 0
BEGIN
SET NOCOUNT ON
SELECT 'Syncing feed data for ' + CompanyName FROM Company WHERE CompanyId = @cid
SET NOCOUNT OFF
-- n/a --------------------------------------------------------------------------------------------------------------------------------------------------------------------
--SELECT a.*
-- , p.*
-- FROM RIVFeeds..AutoWithImage a
-- INNER JOIN Product p ON a.StockNumber = p.SKU
-- WHERE ClientID = @ClientID
-- AND a.Active = 1
-- AND a.Updated <= p.LastFeedUpdate
-- Needs UPDATE -----------------------------------------------------------------------------------------------------------------------------------------------------------
PRINT '--[ UPDATE ]--'
UPDATE Product
SET [Description] = ''
, [Image] = a.ImageURL
, isDeleted = a.Active ^ 1
, isFromFeed = 1
, LastFeedUpdate = a.Updated
, LowestPrice = a.GuaranteedSalePrice
, RetailPrice = a.ListPrice
, [Title] = ''
, Updated = GETUTCDATE()
, UpdatedBy = 'Feed Sync Process'
FROM RIVFeeds..AutoWithImage a
INNER JOIN Product p ON a.StockNumber = p.SKU AND a.AutoID = p.alternateProductID
WHERE ClientID = @ClientID
AND p.CompanyID = @cid
AND a.Updated > p.LastFeedUpdate
-- Needs BACKUP -----------------------------------------------------------------------------------------------------------------------------------------------------------
PRINT '--[ BACKUP #1 ]--'
INSERT INTO ProductDeleted(ProductId, alternateProductID, CompanyID, CharacterId, URLDomain, SKU, Title, Description, ButtonConfig, RetailPrice, LowestPrice, Image
, BackgroundColor, FontColor, buttonPositionCSS, isFromFeed, isDeleted, LastFeedUpdate, Created, CreatedBy, Updated, UpdatedBy)
SELECT p.ProductId, p.alternateProductID, p.CompanyID, p.CharacterId, p.URLDomain, p.SKU, p.Title, p.Description, p.ButtonConfig, p.RetailPrice, p.LowestPrice, p.Image
, p.BackgroundColor, p.FontColor, p.buttonPositionCSS, p.isFromFeed, p.isDeleted, p.LastFeedUpdate, p.Created, p.CreatedBy, GETUTCDATE(), 'Feed Sync Process'
FROM Product p
WHERE p.isDeleted = 1
AND p.CompanyID = @cid
-- Needs DELETE -----------------------------------------------------------------------------------------------------------------------------------------------------------
PRINT '--[ DELETE #1 ]--'
DELETE FROM Product
WHERE CompanyID = @cid
AND isDeleted = 1
-- Needs INSERT -----------------------------------------------------------------------------------------------------------------------------------------------------------
PRINT '--[ INSERT ]--'
INSERT INTO Product(ProductId, alternateProductID, CompanyID, CharacterId, URLDomain, SKU, Title, Description, ButtonConfig, RetailPrice, LowestPrice, Image
, BackgroundColor, FontColor, buttonPositionCSS, isFromFeed, isDeleted, LastFeedUpdate, Created, CreatedBy)
SELECT NEWID()
, a.AutoID
, @cid
, ''
, ''
, a.StockNumber
, ''
, ''
, ''
, a.ListPrice
, a.GuaranteedSalePrice
, COALESCE(a.ImageURL, '')
, ''
, ''
, ''
, 1
, 0
, a.Updated
, GETUTCDATE()
, 'Feed Sync Process'
FROM RIVFeeds..AutoWithImage a
WHERE a.ClientID = @ClientID
AND a.StockNumber NOT IN (SELECT p.sku FROM Product p WHERE CompanyID = @cid AND isFromFeed = 1)
AND a.AutoID NOT IN (SELECT p.alternateProductID FROM Product p WHERE CompanyID = @cid AND isFromFeed = 1)
AND a.Active = 1
--PRINT @cid
FETCH NEXT FROM c1 INTO @cid
END
CLOSE c1
DEALLOCATE c1
END
GO
现在,我使用实体框架(尚未完成)在代码中编写它:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RivWorks.Model;
using RivWorks.Model.Entities;
using RivWorks.Model.Feeds;
using RivWorks.Model.RivData;
using model = RivWorks.Model.Entities;
namespace RivWorks.Controller.Sync
{
public static class Feeds
{
#region Public Methods
public static bool Product(long ClientID)
{
bool retFlag = true;
DateTime startTime = DateTime.Now;
DateTime splitTime = startTime;
Guid companyID;
DateTime createdUpdated = DateTime.UtcNow;
string createdUpdatedBy = "Feed Sync Process";
List<SyncMessage> Activity = new List<SyncMessage>();
List<model.Product> insertProductList = new List<Product>();
List<model.Product> updateProductList = new List<Product>();
List<model.Product> deleteProductList = new List<Product>();
using (RivEntities _dbRiv = new RivWorksStore(Stores.RivConnString).NegotiationEntities())
{
using (FeedsEntities _dbFeed = new FeedStoreReadOnly(Stores.FeedConnString).ReadOnlyEntities())
{
List<model.AutoWithImage> feedProductList = _dbFeed.AutoWithImage.Where(a => a.ClientID == ClientID).ToList();
List<model.vwCompanyDetails> companyDetailList = _dbRiv.vwCompanyDetails.Where(a => a.ClientID == ClientID).ToList();
foreach (model.vwCompanyDetails companyDetail in companyDetailList)
{
companyID = companyDetail.CompanyId;
List<model.Product> rivProductList = _dbRiv.Product.Include("Company").Where(a => a.Company.CompanyId == companyID).ToList();
#region Handle UPDATES...
var updateFeedProductList = from f in feedProductList
join r in rivProductList
on f.AutoID equals r.alternateProductID
where f.Updated > r.LastFeedUpdate.Value || f.Active == false
select f;
var updateRivProductList = from r in rivProductList
join f in feedProductList
on r.alternateProductID equals f.AutoID
where f.Updated > r.LastFeedUpdate.Value || f.Active == false
select r;
foreach (model.AutoWithImage feedProduct in updateFeedProductList)
{
bool alreadyExists = false;
foreach (model.Product rivProduct in updateRivProductList)
{
if (feedProduct.StockNumber == rivProduct.SKU && feedProduct.AutoID == rivProduct.alternateProductID)
{
alreadyExists = true;
// Active feed items...
if (feedProduct.Active)
{
// Changed since last sync...
if (feedProduct.Updated > rivProduct.LastFeedUpdate)
{
rivProduct.ProductId = rivProduct.ProductId;
rivProduct.Company = rivProduct.Company;
rivProduct.alternateProductID = feedProduct.AutoID;
rivProduct.Description = String.Empty.EnforceNoNull();
rivProduct.Image = feedProduct.ImageURL.EnforceNoNull();
rivProduct.isDeleted = false;
rivProduct.isFromFeed = true;
rivProduct.LastFeedUpdate = feedProduct.Updated;
rivProduct.LowestPrice = feedProduct.GuaranteedSalePrice;
rivProduct.RetailPrice = feedProduct.ListPrice;
rivProduct.Title = String.Empty.EnforceNoNull();
rivProduct.Updated = createdUpdated;
rivProduct.UpdatedBy = createdUpdatedBy;
}
// Not changed since last sync...
else if (feedProduct.Updated <= rivProduct.LastFeedUpdate)
{
// nop
}
}
}
}
}
_dbRiv.SaveChanges();
#endregion
#region Handle DELETES...
List<model.Product> deleteRivProductList = _dbRiv.Product
.Include("Company")
.Where(a => a.Company.CompanyId == companyID
&& a.isDeleted == true)
.ToList();
// transfer to ProductDelete table...
foreach (model.Product delProduct in deleteRivProductList)
{
model.ProductDeleted productDeleted = new ProductDeleted();
productDeleted.alternateProductID = delProduct.alternateProductID;
productDeleted.BackgroundColor = delProduct.BackgroundColor;
productDeleted.ButtonConfig = delProduct.ButtonConfig;
productDeleted.buttonPositionCSS = delProduct.buttonPositionCSS;
productDeleted.CharacterId = delProduct.CharacterId;
productDeleted.CompanyID = companyID;
productDeleted.Created = delProduct.Created;
productDeleted.CreatedBy = delProduct.CreatedBy;
productDeleted.Description = delProduct.Description;
productDeleted.FontColor = delProduct.FontColor;
productDeleted.Image = delProduct.Image;
productDeleted.isDeleted = delProduct.isDeleted;
productDeleted.isFromFeed = delProduct.isFromFeed;
productDeleted.LastFeedUpdate = delProduct.LastFeedUpdate;
productDeleted.LowestPrice = delProduct.LowestPrice;
productDeleted.ProductId = delProduct.ProductId;
productDeleted.RetailPrice = delProduct.RetailPrice;
productDeleted.SKU = delProduct.SKU;
productDeleted.Title = delProduct.Title;
productDeleted.Updated = createdUpdated;
productDeleted.UpdatedBy = createdUpdatedBy;
productDeleted.URLDomain = delProduct.URLDomain;
_dbRiv.AddToProductDeleted(productDeleted);
}
int moves = _dbRiv.SaveChanges();
// delete the records...
foreach (model.Product delProduct in deleteRivProductList)
{
_dbRiv.DeleteObject(delProduct);
}
int deletes = _dbRiv.SaveChanges();
#endregion
#region Handle INSERTS...
// to be written...
#endregion
}
}
}
return retFlag; // remember to set this...
}
#endregion
}
}
我知道现在有点混乱。 我将其包括在内,因此,如果有人对如何更好地进行清理,使用EF进行此操作的更好方法等有任何建议,我将不胜感激。 我知道在实体之间进行联接有一些非常巧妙的方法,他们想学习而不是朝自己的脚开枪。
您实际上在哪里插入或删除记录? 我看到您将它们添加到insertProductList
和deleteProductList
,但是您从未在表_dbRiv.Product
上调用Insert或Delete。
我认为您要完成的工作如下:
//perform all updates
_dbRiv.SubmitChanges();
//perform all deletes
_dbRiv.Product.DeleteAllOnSubmit(deleteProductList);
_dbRiv.SubmitChanges();
//perform inserts, one at a time
foreach(model.Product p in insertProductList)
{
_dbRiv.Product.InsertOnSubmit(p);
_dbRiv.SubmitChanges();
}
但是,尚不清楚您期望如何执行更新。 似乎不是创建model.Product
的新实例并设置其属性,而是应该更新rivProduct
的属性。 否则,你的代码,我相信你会需要附加updateProduct
使用_dbRiv.Product.Attach(updateProduct, rivProduct)
让L2S应当知道其性质已经改变。
我现在有运行代码。 由于没有其他人在回答,因此我不得不假设我朝着正确的方向前进。 谢谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.