সত্তা ম্যানেজারটি বন্ধ রয়েছে


87
[Doctrine\ORM\ORMException]   
The EntityManager is closed.  

ডেটা whenোকানোর সময় আমি একটি ডিবিএল ব্যতিক্রম পাওয়ার পরে, অ্যান্টিটি ম্যানেজারটি বন্ধ হয়ে যায় এবং আমি এটি পুনরায় সংযোগ করতে পারছি না।

আমি এরকম চেষ্টা করেছিলাম কিন্তু এটি সংযোগ পায়নি।

$this->em->close();
$this->set('doctrine.orm.entity_manager', null);
$this->set('doctrine.orm.default_entity_manager', null);
$this->get('doctrine')->resetEntityManager();
$this->em = $this->get('doctrine')->getEntityManager();

আবার কেউ কীভাবে পুনরায় সংযোগ করবেন?


সত্তা পরিচালক কেন বন্ধ হয়?
জে শেঠ

4
@ জায়েশেথ সত্তা ব্যবস্থাপক একটি ডিবিএল ব্যতিক্রমের পরে বন্ধ হতে পারে, বা যদি আপনি কোনও সত্ত্বা ম্যানেজার-> সাফ করতে পারেন (ফ্লাশের আগে)। আমি কিছু লোককে মৃত্যুদন্ড প্রবাহ শাখার জন্য DBAL ব্যতিক্রমগুলি ব্যবহার করে দেখেছি এবং তারপরে একটি অ্যান্টিটি ম্যানেজার বন্ধ হওয়া ত্রুটিটি শেষ করেছি। আপনি যদি এই ত্রুটিটি পেয়ে থাকেন তবে আপনার প্রোগ্রামে সম্পাদনের প্রবাহে কিছু সমস্যা আছে।
ILikeTacos

4
@ অ্যালান চাভেজ - আমি এই ত্রুটিটি পাচ্ছি কারণ আমি একাধিক থ্রেড দ্বারা একসাথে অ্যাক্সেস করা টেবিলের জন্য একটি সেমফোর পতাকা লিখতে মতবাদ ব্যবহার করছি। মাইএসকিউএল দুটি সেমফোর তৈরির চেষ্টা করে প্রতিযোগিতামূলক দুটি থ্রেডের মধ্যে একটিকে ত্রুটিযুক্ত করবে, কারণ মূল সীমাবদ্ধতার অর্থ এর মধ্যে কেবল একটি সফল হতে পারে। আইএমও মতবাদের মধ্যে একটি ত্রুটি রয়েছে যা আপনাকে প্রত্যাশিত মাইএসকিউএল ত্রুটিগুলি নিরাপদে পরিচালনা করতে দেয় না । একটি INSERT বিবৃতিতে বিরোধ রয়েছে বলে কেন পুরো মাইএসকিউএল সংযোগটি সংযোগ বিচ্ছিন্ন করা উচিত?
স্ট্যাম্পি কোড

4
আপনি যদি কোনও ডাটাবেসে ব্যতিক্রমগুলি লগ করার চেষ্টা করছেন app.exception_listenerতবে ব্যতিক্রম (যেমন সীমাবদ্ধতা লঙ্ঘন) সংযোগটি বন্ধ করে দিলে আপনি এই ত্রুটিটিও দেখতে পাবেন ।
Lg102

উত্তর:


25

এটি একটি খুব জটিল সমস্যা, যেহেতু কমপক্ষে সিমফনি ২.০ এবং মতবাদ ২.১ এর ক্ষেত্রে, সত্তা ম্যানেজারটি বন্ধ হয়ে যাওয়ার পরে এটি কোনওভাবেই খোলা সম্ভব নয়।

এই সমস্যাটি কাটিয়ে ওঠার একমাত্র উপায় হ'ল আপনার নিজের ডিবিএল সংযোগ শ্রেণি তৈরি করা, মতবাদটি মুড়ে ফেলা এবং ব্যতিক্রম হ্যান্ডলিং সরবরাহ করা (উদাহরণস্বরূপ এন্টি ম্যানেজারের ব্যতিক্রমটি পপ করার আগে বেশ কয়েকবার চেষ্টা করা)। এটি কিছুটা হ্যাকি এবং আমি আশঙ্কা করি যে এটি ট্রানজেকশনাল পরিবেশে কিছুটা অসঙ্গতি সৃষ্টি করতে পারে (উদাহরণস্বরূপ, যদি ব্যর্থ ক্যোয়ারী কোনও লেনদেনের মাঝামাঝি হয় তবে কী ঘটে যায় তা সম্পর্কে আমি সত্যিই নিশ্চিত নই)।

এই পথে যাওয়ার জন্য একটি উদাহরণ কনফিগারেশন হ'ল:

doctrine:
  dbal:
    default_connection: default
    connections:
      default:
        driver:   %database_driver%
        host:     %database_host%
        user:     %database_user%
        password: %database_password%
        charset:  %database_charset%
        wrapper_class: Your\DBAL\ReopeningConnectionWrapper

ক্লাসটি কমবেশি এর মতো শুরু করা উচিত:

namespace Your\DBAL;

class ReopeningConnectionWrapper extends Doctrine\DBAL\Connection {
  // ...
}

একটি খুব বিরক্তিকর বিষয় হ'ল আপনাকে ব্যতিক্রম-পরিচালনার মোড়ক সরবরাহ করে সংযোগের প্রতিটি পদ্ধতি ওভাররাইড করতে হবে। ক্লোজার ব্যবহারের ফলে কিছুটা ব্যথা সহজ হতে পারে।


74

আমার সমাধান।

কিছু পরীক্ষা করার আগে:

if (!$this->entityManager->isOpen()) {
    $this->entityManager = $this->entityManager->create(
        $this->entityManager->getConnection(),
        $this->entityManager->getConfiguration()
    );
}

সমস্ত সত্তা সংরক্ষণ করা হবে। তবে এটি নির্দিষ্ট শ্রেণি বা কিছু ক্ষেত্রে কার্যকর। যদি আপনার ইনজেকশনের সত্তা প্রশাসক সহ কিছু পরিষেবা থাকে তবে এটি এখনও বন্ধ থাকবে।


এই উপায়টি আরও ভাল যখন ডাই ধারকটি নিজেই উপলব্ধ থাকে না। ধন্যবাদ.
হরি কেটি

4
আপনি তৃতীয় প্যারামিটারে $ এই- >টিটিটি ম্যানেজার-> getEventManager () পাস করতেও চাইতে পারেন।
মেধাত গায়দ

34

সিমফনি ২.০ :

$em = $this->getDoctrine()->resetEntityManager();

সিমফনি ২.১+ :

$em = $this->getDoctrine()->resetManager();

6
সতর্কতা: resetEntityManager সিমফনি ২.১ থেকে অবহেলিত। resetManagerপরিবর্তে ব্যবহার করুন
ফ্রান্সেস্কো ক্যাসুলা

এটি কি কাজের ইউনিটটি পুনরায় সেট করে?
ফ্লু

@ ফ্লু এনটিটি ম্যানেজার শ্রেণি ইউনিট অফ ওয়ার্ক ক্লাস পরিচালনা করে বিবেচনা করে আমার সন্দেহ হয় যে এটি হবে। তবে, আমি এটি পরীক্ষা করিনি তাই নিশ্চিত হতে পারে না।
রাইল

28

এভাবেই আমি এই মতবাদটির সমাধান করেছি "দ্য ইন্টিটি ম্যানেজারটি বন্ধ is" সমস্যা. মূলত প্রতিবারই একটি ব্যতিক্রম (যেমন ডুপ্লিকেট কী) বা বাধ্যতামূলক কলামের জন্য ডেটা সরবরাহ না করার কারণে ডক্ট্রাইন সত্তা পরিচালককে বন্ধ করে দেবে। আপনি যদি এখনও ডাটাবেসের সাথে ইন্টারঅ্যাক্ট করতে চান তবে জেগ্রিননresetManager() দ্বারা উল্লিখিত পদ্ধতিটিতে কল করে আপনাকে সত্তা ম্যানেজারটি পুনরায় সেট করতে হবে ।

আমার অ্যাপ্লিকেশনটিতে আমি একাধিক রব্বিটএমকিউ ভোক্তা চালাচ্ছিলাম যা সবাই একই কাজ করত: ডাটাবেসে কোনও সত্তা ছিল কিনা তা পরীক্ষা করে, হ্যাঁ যদি এটি তৈরি করে না, তবে এটি তৈরি না করে আবার ফিরিয়ে দিন। যদি সেই সত্তা ইতিমধ্যে বিদ্যমান ছিল কিনা তা যাচাই করে অন্য গ্রাহক তৈরি করার মধ্যবর্তী কয়েক মিলি সেকেন্ডে এটি একই রকম ঘটেছে এবং অনুপস্থিত সত্তা তৈরি করে যা অন্য ভোক্তাকে একটি নকল কী ব্যতিক্রম ( বর্ণের শর্ত ) দ্বারা ব্যয় করে।

এটি একটি সফ্টওয়্যার ডিজাইনের সমস্যা তৈরি করেছিল। মূলত আমি যা করার চেষ্টা করছিলাম তা হ'ল একটি লেনদেনে সমস্ত সত্তা তৈরি করা। এটি বেশিরভাগের কাছেই স্বাভাবিক অনুভূত হতে পারে তবে আমার ক্ষেত্রে এটি অবশ্যই ধারণাগতভাবে ভুল ছিল। নিম্নলিখিত সমস্যাটি বিবেচনা করুন: আমাকে একটি ফুটবল ম্যাচ সত্তা সংরক্ষণ করতে হয়েছিল যার মধ্যে এই নির্ভরতা ছিল।

  • একটি গ্রুপ (যেমন গ্রুপ এ, গ্রুপ বি ...)
  • একটি রাউন্ড (যেমন সেমি ফাইনাল ...)
  • একটি ভেন্যু (মানে স্টেডিয়াম যেখানে ম্যাচটি হচ্ছে)
  • ম্যাচের স্থিতি (যেমন অর্ধবার, পুরো সময়)
  • দুটি দল ম্যাচ খেলছে
  • ম্যাচ নিজেই

এখন, কেন ভেন্যু তৈরি করা ম্যাচের মতো একই লেনদেনের মধ্যে হওয়া উচিত? এটি হতে পারে যে আমি সবেমাত্র একটি নতুন ভেন্যু পেয়েছি যা এটি আমার ডাটাবেসে নেই তাই আমাকে এটি তৈরি করতে হবে। তবে এটি এমনও হতে পারে যে ভেন্যুটি অন্য ম্যাচটি হোস্ট করতে পারে তাই অন্য গ্রাহক সম্ভবত এটি একই সাথে তৈরি করার চেষ্টা করবে। সুতরাং আমাকে যা করতে হবে তা হ'ল পৃথক লেনদেনের মধ্যে প্রথমে সমস্ত নির্ভরতা তৈরি করা হয়েছিল তা নিশ্চিত করে আমি সত্তা পরিচালককে একটি সদৃশ কী ব্যতিক্রমতে পুনরায় সেট করছি। আমি বলব যে ম্যাচের পাশের সেখানে থাকা সমস্ত সত্তাকে "ভাগ করে নেওয়া" হিসাবে সংজ্ঞায়িত করা যেতে পারে কারণ তারা সম্ভবত অন্যান্য গ্রাহকদের অন্যান্য লেনদেনের অংশ হতে পারে। সেখানে "ভাগ" করা হয়নি এমন কিছু মিলটি নিজেই রয়েছে যা সম্ভবত একই সাথে দুটি গ্রাহক তৈরি করতে পারবেন না।

এই সবগুলি আরও একটি সমস্যার দিকে পরিচালিত করেছিল। আপনি যদি সত্তা পরিচালককে পুনরায় সেট করেন, পুনরায় সেট করার আগে আপনি যে সমস্ত বস্তু পুনরুদ্ধার করেছেন তা ডক্ট্রিনের জন্য সম্পূর্ণ নতুন। সুতরাং মতবাদ তাদের উপর একটি আপডেট আপডেট চালানোর চেষ্টা করবে না তবে একটি সংযোজন ! সুতরাং নিশ্চিত হয়ে নিন যে আপনি আপনার সমস্ত নির্ভরতা যুক্তিসঙ্গতভাবে সঠিক লেনদেনের ক্ষেত্রে তৈরি করেছেন এবং তারপরে আপনার সমস্ত অবজেক্টগুলি লক্ষ্য সত্তায় সেট করার আগে ডাটাবেস থেকে ফিরে পাবেন। নিম্নলিখিত কোডটি উদাহরণ হিসাবে বিবেচনা করুন:

$group = $this->createGroupIfDoesNotExist($groupData);

$match->setGroup($group); // this is NOT OK!

$venue = $this->createVenueIfDoesNotExist($venueData);

$round = $this->createRoundIfDoesNotExist($roundData);

/**
 * If the venue creation generates a duplicate key exception
 * we are forced to reset the entity manager in order to proceed
 * with the round creation and so we'll loose the group reference.
 * Meaning that Doctrine will try to persist the group as new even
 * if it's already there in the database.
 */

সুতরাং এটি আমার মনে হয় এটি করা উচিত।

$group = $this->createGroupIfDoesNotExist($groupData); // first transaction, reset if duplicated
$venue = $this->createVenueIfDoesNotExist($venueData); // second transaction, reset if duplicated
$round = $this->createRoundIfDoesNotExist($roundData); // third transaction, reset if duplicated

// we fetch all the entities back directly from the database
$group = $this->getGroup($groupData);
$venue = $this->getVenue($venueData);
$round = $this->getGroup($roundData);

// we finally set them now that no exceptions are going to happen
$match->setGroup($group);
$match->setVenue($venue);
$match->setRound($round);

// match and teams relation...
$matchTeamHome = new MatchTeam();
$matchTeamHome->setMatch($match);
$matchTeamHome->setTeam($teamHome);

$matchTeamAway = new MatchTeam();
$matchTeamAway->setMatch($match);
$matchTeamAway->setTeam($teamAway);

$match->addMatchTeam($matchTeamHome);
$match->addMatchTeam($matchTeamAway);

// last transaction!
$em->persist($match);
$em->persist($matchTeamHome);
$em->persist($matchTeamAway);
$em->flush();

আমি আসা করি এটা সাহায্য করবে :)


চমত্কার ব্যাখ্যা। আমি অনুরূপ কিছু পেয়েছি এবং ভেবেছিলাম আপনার উত্তরে অবদান রাখতে ভাল লাগবে। আপনাকে অনেক ধন্যবাদ.
অঞ্জনা সিলভা

17

আপনি আপনার EM পুনরায় সেট করতে পারেন

// reset the EM and all aias
$container = $this->container;
$container->set('doctrine.orm.entity_manager', null);
$container->set('doctrine.orm.default_entity_manager', null);
// get a fresh EM
$em = $this->getDoctrine()->getManager();

10

ইন Symfony 4.2+ আপনি প্যাকেজ ব্যবহার করতে হবে:

composer require symfony/proxy-manager-bridge

অন্যথায় আপনি ব্যতিক্রম পাবেন:

Resetting a non-lazy manager service is not supported. Declare the "doctrine.orm.default_entity_manager" service as lazy.  

আপনি যেমন সত্তা ম্যানেজারটি পুনরায় সেট করতে পারেন তার চেয়ে বেশি:

পরিষেবাদি.আইএমএল:

App\Foo:
    - '@doctrine.orm.entity_manager'
    - '@doctrine'

Foo.php:

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\DBAL\DBALException;
use Doctrine\ORM\EntityManagerInterface;


 try {
    $this->entityManager->persist($entity);
    $this->entityManager->flush();
} catch (DBALException $e) {
    if (!$this->entityManager->isOpen()) {
        $this->entityManager = $this->doctrine->resetManager();
    }
}

4

নিয়ামক মধ্যে।

ব্যতিক্রম সত্তা পরিচালককে বন্ধ করে দেয়। এটি বাল্ক প্রবেশের জন্য ঝামেলা করে troubles চালিয়ে যেতে, এটি নতুন সংজ্ঞা দিতে হবে।

/** 
* @var  \Doctrine\ORM\EntityManager
*/
$em = $this->getDoctrine()->getManager();

foreach($to_insert AS $data)
{
    if(!$em->isOpen())
    {
        $this->getDoctrine()->resetManager();
        $em = $this->getDoctrine()->getManager();
    }

  $entity = new \Entity();
  $entity->setUniqueNumber($data['number']);
  $em->persist($entity);

  try
  {
    $em->flush();
    $counter++;
  }
  catch(\Doctrine\DBAL\DBALException $e)
  {
    if($e->getPrevious()->getCode() != '23000')
    {   
      /**
      * if its not the error code for a duplicate key 
      * value then rethrow the exception
      */
      throw $e;
    }
    else
    {
      $duplication++;
    }               
  }                      
}

2

এটির মূল্য কীসের জন্য আমি পেয়েছি যে এই সমস্যাটি একটি ব্যাচ আমদানি কমান্ডে ঘটছিল কারণ একটি এসকিউএল ত্রুটি ধরা (চেষ্টা করে em->flush()) যা আমি সম্পর্কে কিছুই করি নি এর ফলে ক্যাচ লুপের কারণে । আমার ক্ষেত্রে এটি ছিল কারণ আমি নাল হিসাবে ফেলে রাখা অ-অযোগ্য সম্পত্তি সহ একটি রেকর্ড toোকানোর চেষ্টা করছিলাম।

সাধারণত এটি একটি সমালোচনামূলক ব্যতিক্রম ঘটবে এবং কমান্ড বা নিয়ামককে থামিয়ে দেবে, তবে আমি কেবল এই সমস্যাটির পরিবর্তে লগ করছি এবং চালিয়ে যাচ্ছি। এসকিউএল ত্রুটিটি সত্তা পরিচালককে বন্ধ করে দেয়।

dev.logএই জাতীয় কোনও এসকিউএল ত্রুটির জন্য আপনার ফাইলটি পরীক্ষা করুন কারণ এটি আপনার দোষ হতে পারে। :)



1

সিমফনি ৪.৩.২-এর পরিবর্তনগুলি পরীক্ষা করার সময় আমি একই সমস্যার মুখোমুখি হয়েছিলাম

আমি লগ স্তর INFO এ নামিয়েছি

এবং আবার পরীক্ষা চালিয়েছে

এবং লগ এই দেখায়:

console.ERROR: Error thrown while running command "doctrine:schema:create". Message: "[Semantical Error] The annotation "@ORM\Id" in property App\Entity\Common::$id was never imported. Did you maybe forget to add a "use" statement for this annotation?" {"exception":"[object] (Doctrine\\Common\\Annotations\\AnnotationException(code: 0): [Semantical Error] The annotation \"@ORM\\Id\" in property App\\Entity\\Common::$id was never imported. Did you maybe forget to add a \"use\" statement for this annotation? at C:\\xampp\\htdocs\\dirty7s\\vendor\\doctrine\\annotations\\lib\\Doctrine\\Common\\Annotations\\AnnotationException.php:54)","command":"doctrine:schema:create","message":"[Semantical Error] The annotation \"@ORM\\Id\" in property App\\Entity\\Common::$id was never imported. Did you maybe forget to add a \"use\" statement for this annotation?"} []

এর অর্থ কোডে কিছু ত্রুটি নিম্নলিখিত কারণগুলির:

Doctrine\ORM\ORMException: The EntityManager is closed.

সুতরাং লগ চেক করা ভাল ধারণা


প্রথমটির সাথে দ্বিতীয়টির সাথে সম্পর্কিত সম্পর্কিত কীভাবে আপনি অতিরিক্ত তথ্য সরবরাহ করতে পারেন?
জর্জি নভিক

1

সিমফনি v4.1.6

মতবাদ v2.9.0

একটি সংগ্রহস্থলে সদৃশ সন্নিবেশ প্রক্রিয়া

  1. আপনার রেপোতে একটি রেজিস্ট্রি অ্যাক্সেস পান


    //begin of repo
    
    /** @var RegistryInterface */
    protected $registry;
    
    public function __construct(RegistryInterface $registry)
    {
        $this->registry = $registry;
        parent::__construct($registry, YourEntity::class);
    }

  1. ঝুঁকিপূর্ণ কোডটি লেনদেনের মধ্যে আবদ্ধ করুন এবং ব্যতিক্রমের ক্ষেত্রে রিসেট ম্যানেজার


    //in repo method
    $em = $this->getEntityManager();
    
    $em->beginTransaction();
    try {
        $em->persist($yourEntityThatCanBeDuplicate);
        $em->flush();
        $em->commit();
    
    } catch (\Throwable $e) {
        //Rollback all nested transactions
        while ($em->getConnection()->getTransactionNestingLevel() > 0) {
            $em->rollback();
        }
        
        //Reset the default em
        if (!$em->isOpen()) {
            $this->registry->resetManager();
        }
    }


0

আমি এই সমস্যা ছিল। এই আমি এটি স্থির।

ফ্ল্যাশ বা চালিয়ে যাওয়ার চেষ্টা করার সময় সংযোগটি বন্ধ হয়ে গেছে বলে মনে হচ্ছে। এটি আবার খোলার চেষ্টা করা একটি খারাপ পছন্দ কারণ নতুন সমস্যা তৈরি করে। কেন সংযোগটি বন্ধ ছিল তা বোঝার চেষ্টা করেছি এবং দেখতে পেলাম যে আমি অজানা থাকার আগে অনেক বেশি পরিবর্তন করছি।

জারি করা () এর আগে সমস্যা সমাধান হয়েছে solved


0

এটি সত্যিই পুরানো সমস্যা, তবে আমার ঠিক একইরকম সমস্যা হয়েছিল। আমি এরকম কিছু করছিলাম:

// entity
$entityOne = $this->em->find(Parent::class, 1);

// do something on other entites (SomeEntityClass)
$this->em->persist($entity);
$this->em->flush();
$this->em->clear();

// and at end I was trying to save changes to first one by
$this->em->persist($entityOne);
$this->em->flush();
$this->em->clear();

সমস্যাটি হ'ল পরিষ্কার ছিল প্রথমটি সহ সমস্ত সত্তাকে আলাদা করে দেওয়া এবং ত্রুটিযুক্ত ত্রুটিটি অ্যান্টিটি ম্যানেজারটি বন্ধ রয়েছে।

আমার ক্ষেত্রে সমাধানটি ছিল স্বতন্ত্র প্রকারের সত্তা সম্পর্কে পরিষ্কার করা এবং $entityOneএখনও ইএম এর অধীনে ছেড়ে যাওয়া :

$this->em->clear(SomeEntityClass::class);

মতবাদকে \ ওআরএম \ সত্তা ম্যানেজার কল করা :: নির্দিষ্ট সত্তা সাফ করার জন্য যে কোনও যুক্তি সহ পরিষ্কার () সাফ করা হয় এবং তা মতবাদ
ওআরএম in.০-এ

0

একটি সাধারণ কোড রিফ্যাক্টরিং সহ একই সমস্যা। সমস্যাটি এমন কিছু সময় উপস্থিত থাকে যখন প্রয়োজনীয় ক্ষেত্রটি শূন্য হয়, অ্যানিথিংয়ের আগে আপনার কোডটি রিফ্যাক্টর করার চেষ্টা করুন। একটি ভাল কর্মপ্রবাহ সমস্যার সমাধান করতে পারে।


-1

সিমফনি 5 / ডক্ট্রিন 2 ব্যবহার করার ক্ষেত্রে আমার একই ত্রুটি ছিল my আপনি যখন কোনও সংরক্ষিত শব্দ ব্যবহার করতে চান, তখন আপনাকে ব্যাক-টিক ব্যবহার করে এর নামটি এড়াতে হবে। টীকাগুলির আকারে:

@ORM\Column(name="`order`", type="integer", nullable=false)


-2

আমিও একই সমস্যার মুখোমুখি হয়েছি। এখানে বেশ কয়েকটি স্থান দেখার পরে আমি এটির সাথে কীভাবে আচরণ করেছি।

//function in some model/utility
function someFunction($em){
    try{
        //code which may throw exception and lead to closing of entity manager
    }
    catch(Exception $e){
        //handle exception
        return false;
    }
    return true;
}

//in controller assuming entity manager is in $this->em 
$result = someFunction($this->em);
if(!$result){
    $this->getDoctrine()->resetEntityManager();
    $this->em = $this->getDoctrine()->getManager();
}

আশা করি এটি কাউকে সাহায্য করবে!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.