以下是我的代码:
protected void SubmitCSV_Click(object sender, ImageClickEventArgs e)
{ //Check Routes File Uploader for file
if (ImportCSV.HasFile)
{
//Get File name
string fileName = ImportCSV.FileName;
//Read CSV
StreamReader ReadUploadedFile = new StreamReader(ImportCSV.FileContent);
//Parse CSV
var pathOfCSVFile = ReadUploadedFile;
//Gather CSV contents
var adapter = new GenericParsing.GenericParserAdapter(pathOfCSVFile);
//Ignore first row
adapter.FirstRowHasHeader = true;
DataTable TempRouteDataTable = adapter.GetDataTable();
if (ExcelDDL.SelectedValue == "Active Service Keys" && fileName == "ActiveServiceKeys.csv")
{
SEPTA_DS.ActiveServiceKeysTBLDataTable GetActiveServiceKeys = (SEPTA_DS.ActiveServiceKeysTBLDataTable)askta.GetData();
var hasData = GetActiveServiceKeys.Rows.Count > 0;
//Loop through each row and insert into database
foreach (DataRow row in TempRouteDataTable.Rows)
{
//Gather column headers
var category = Convert.ToString(CategoryDDL.SelectedItem);
var agency = Convert.ToString(row["Agency"]);
var route = Convert.ToString(row["Route"]);
var direction = Convert.ToString(row["Direction"]);
var serviceKey = Convert.ToString(row["Service Key"]);
var language = Convert.ToString(row["Language"]);
var activeServiceKeys = Convert.ToString(row["Active Service Keys"]);
//Check if data already exists
if (hasData == true)
{
var originalID = Convert.ToInt32(GetActiveServiceKeys.Rows[0] ["ActiveServiceKeysID"]);
int updateData = Convert.ToInt32(askta.UpdateActiveServiceKeys(category, agency, route, direction, serviceKey, language, activeServiceKeys, originalID));
}
else
{
int insertData = Convert.ToInt32(askta.InsertActiveServiceKeys(category, agency, route, direction, serviceKey, language, activeServiceKeys));
}
}
}
}
}
行存在后出现问题。 foreach
当前正在读取已上传的CSV,因此在foreach
被触发时,它会在数据库中放置一行。
编辑:
当数据库中不存在数据时,我想运行insert
方法。
如果它存在,我想运行update
方法。
问题:运行update
方法时,需要originalID
(自动递增int)。由于上传CSV中的每一行都在foreach
范围内,因此我不熟悉如何获取originalID
每个循环。
目前,(刚刚修复)我有一个0,但每个循环不会改变。
答案 0 :(得分:1)
我同意其他人的困惑,但这里有一个观察结果:将Update和Insert逻辑建立在存在一些现有数据的事实上可能不是一个好主意。如果CSV包含一个新行和一行要更新怎么办?如果现有数据与CSV中的数据完全不重叠怎么办?
你可能希望有像Alvin提到的那样的逻辑,它从行中提取ID。之后,检查数据库中是否存在ID,并使用结果确定它是插入还是更新。
答案 1 :(得分:1)
考虑重构代码以使用LINQ和面向对象的解决方案。这将使阅读和阅读更容易维持!
创建一个类来镜像数据表的行。在这里,我称之为MyDTO
foreach ( var item in dt.Rows.Cast<DataRow>().Select(r=> new MyDTO {
category = CategoryDDL.SelectedItem.ToString(),
agency = r["Agency"].ToString(),
route = r["Route"].ToString(),
direction = r["Direction"].ToString(),
serviceKey= r["Service Key"].ToString(),
language = r["Language"].ToString(),
originalID = GetActiveServiceKeys.Rows[r["Active Service Keys"].ToString()]
activeServiceKeys = r["Active Service Keys"].ToString()}
))
{
if (!string.IsNullOrEmpty(item.originalID))
int updateData = askta.UpdateActiveServiceKeys(item);
else
int insertData = askta.InsertActiveServiceKeys(item);
}
这要求您将界面更改为askta
方法InsertActiveServiceKeys
和UpdateActiveServiceKeys()
,以采用类型为MyDTO
的参数,而不是一长列值数据类型。更易于维护!
请注意,MyDTO将OriginalID
作为属性,并检查其是否存在已内置于Select
。
Here's a sample on PasteBin。确保您是using System.Linq;
。
答案 2 :(得分:0)
什么是GetActiveServiceKeys? 你不应该试图从行[]上下文中提取该ID吗?
答案 3 :(得分:0)
这一行var originalID = Convert.ToInt32(GetActiveServiceKeys.Rows[ ["ActiveServiceKeysID"]);
并没有多大意义。我从中推断出你要做的是将foreach循环的当前迭代行与GetActiveServiceKeys
表中的特定行匹配,然后获取ActiveServiceKeysID
列的值这样您就可以将它用于更新声明。
以下是需要考虑的一些要点:
根据上传文件中当前行的值,您需要一种方法在GetActiveServiceKeys
表中查找相应的行。理想情况下,您在上传的文件中指定了某种唯一键。没有这样的钥匙吗?我假设上传的文件中没有ActiveServiceKeysID值,否则您可以直接使用它而无需从其他表中查找。是否还有其他一组字段可用于唯一标识行?如果没有,那么在单行上执行简单更新可能是不可能的。
上传的文件是否可以混合使用现有行以及要插入的新行?在您当前的代码中,您基本上根据数据库中是否已有行来决定您是处于“插入”模式还是“更新”模式。我更愿意单独处理每一行,并检查GetActiveServiceKeys
表是否包含与该行匹配的行。
另一种方法是简单地清除当前数据库的ActiveServiceKeys表,并将其替换为上传文件的内容。
答案 4 :(得分:0)
我和p.campbell一起工作过LINQ但是我遇到了太多的错误,虽然我确信我是否有更多时间可以让它工作。
我使用这种方法似乎有效。它检查项目是否存在,如果存在则更新,如果不存在则更新。
//Loop through each row and insert into database
int i = 0;
foreach (DataRow row in TempRouteDataTable.Rows)
{
//Gather column headers
var category = Convert.ToString(CategoryDDL.SelectedItem);
var agency = Convert.ToString(row["Agency"]);
var route = Convert.ToString(row["Route"]);
var direction = Convert.ToString(row["Direction"]);
var serviceKey = Convert.ToString(row["Service Key"]);
var language = Convert.ToString(row["Language"]);
var activeServiceKeys = Convert.ToString(row["Active Service Keys"]);
var origID = -1;
if (GetActiveServiceKeys.Rows.Count > 0)
{
origID = Convert.ToInt32(GetActiveServiceKeys.Rows[i]["ActiveServiceKeysID"]);
var GetID = (SEPTA_DS.ActiveServiceKeysTBLDataTable)askta.GetDataByID(origID);
if (GetID.Rows.Count < 1)
{
origID = -1;
}
}
if (origID == -1)
{
int insertData = Convert.ToInt32(askta.InsertActiveServiceKeys(category, agency, route, direction, serviceKey, language, activeServiceKeys));
}
else
{
int updateData = Convert.ToInt32(askta.UpdateActiveServiceKeys(category, agency, route, direction, serviceKey, language, activeServiceKeys, origID));
}
i++;
}