2010-08-31 98 views
2

在我目前正在使用的项目中,我必须读取一个Excel文件(超过1000行),将它们全部提取并插入/更新到数据库表中。从Excel中插入/更新Doctrine对象

  1. 在性能方面,最好使用fromArray()方法后,所有记录添加到一个Doctrine_Collection和插入/更新他们,对不对?另一种可能的方法是为每一行创建一个新对象(Excel行将是一个对象),然后他们保存它,但我认为它的性能最差。

  2. 每次上载Excel时,都需要将其行与数据库上的现有对象进行比较。如果该行不作为对象存在,则应插入,否则更新。我的第一种方法是将对象和行都转换为数组(或Doctrine_Collections);然后在实施所需操作之前比较两个阵列。

任何人都可以建议我任何其他可能的方法吗?

+0

是您对处理数据库操作(插入/更新)或服务器端代码逻辑(比较阵列)或两个问题吗? – 2010-08-31 20:08:47

+0

两者都好。 – 2010-08-31 20:40:45

+0

不同于我鑫卡特上的第一时刻,数据库的数量是完全使用Doctrine_Collection的fromArray()方法是相同的。无论如何要保存所有在同一请求上组合集合的数组? – 2010-08-31 21:37:51

回答

1

我从来没有在Doctrine_Collections上工作过,但我可以从广义上回答数据库查询和代码逻辑。我将适用以下逻辑: -

  1. 取从数据库中的Excel工作表中的所有行中的单个查询,并将它们存储在一个数组$uploadedSheet

  2. 创建上传的Excel表的所有行的单个数组,称为$storedSheet。我猜Doctrine_Collections $uploadedSheet$storedSheet的结构会相似(两维 - 行,单元格可以被识别和比较)。

3.Run foreach所$uploadedSheet循环如下,只确定哪些需要被插入的行并进行更新(以后做实际查询) -

$rowsToBeUpdated =array(); 
$rowsToBeInserted=array(); 
foreach($uploadedSheet as $row=>$eachRow) 
{ 
    if(is_array($storedSheet[$row])) 
    { 
     foreach($eachRow as $column=>$value) 
     { 
       if($value != $storedSheet[$row][$column]) 
       {//This is a representation of comparison 
        $rowsToBeUpdated[$row]=true; 
        break; //No need to check this row anymore - one difference detected. 
       } 
     } 
    } 
    else 
    { 
     $rowsToBeInserted[$row] = true; 
    } 
} 

4.这样你有两个数组。现在执行2个数据库查询 -

  • 批量插入其数目被存储在$rowsToBeInserted阵列的所有$uploadedSheet那些行。

  • 批量更新$uploadedSheet的所有行,其编号存储在$rowsToBeUpdated数组中。

这些批量查询是提高性能的关键。

让我知道这是否有帮助,或者你想知道别的。

+0

我会仔细分析您的解决方案建议。预先感谢hep。 – 2010-09-02 09:05:03

+0

欢迎您 – 2010-09-02 20:08:56

2

我们最近在一个项目中用CSV数据做了一点。这是相当无痛的。有一个symfony插件tmCsvPlugin,但我们扩展了这一点,因为插件回购的版本已经过时了。必须添加到列表@TODO :)

问题1:

我不明确知道的表现,但我猜想,将记录到Doctrine_Collection,然后调用Doctrine_Collection ::保存()将是最新的方法。我敢肯定,如果一个异常被抛出的地方会很方便,你不得不回滚上次保存..

问题2:

如果你可以用一个行字段作为唯一indentifier ,(让我们假设一个用户名),那么你可以搜索一个现有的记录。如果你发现一个记录,并假设导入的行是一个数组,使用Doctrine_Record :: synchronizeWithArray()来更新该记录;然后将其添加到Doctrine_Collection。完成后,只需拨打Doctrine_Collection ::保存()

一个相当粗糙的“N”准备好执行:

// set up a new collection 
$collection = new Doctrine_Collection('User'); 

// assuming $row is an associative 
// array representing one imported row. 

foreach ($importedRows as $row) { 

    // try to find an existing record 
    // based on a unique identifier. 
    $user = Doctrine_Core::getTable('User') 
     ->findOneByUsername($row['username']); 

    // create a new user record if 
    // no existing record is found. 
    if (!$user instanceof User) { 
     $user = new User(); 
    } 

    // sync record with current data. 
    $user->synchronizeWithArray($row); 

    // add to collection. 
    $collection->add($user); 

} 

// done. save collection. 
$collection->save(); 

相当粗糙,但像这样的工作很适合我。这是假设您可以以某种方式使用导入的行数据作为唯一标识符。

注:如果您使用sf1.2 /学说1.0警惕synchronizeWithArray()的 - 如果我没有记错它没有正确实施。但它在教条1.2中工作正常。

+2

现在,只是一个小幅盘整。用户表对象上被调用的方法必须是findOneByUsername(),否则返回的对象将是一个Doctrine_Collection而不是用户。 – 2010-09-02 10:32:29

+0

对不起,我正在做我的头顶。你绝对正确。固定。 – 2010-09-02 15:22:03