none
There is already an open DataReader RRS feed

  • Вопрос

  • Появляется вот такая ошибка:

    There is already an open DataReader associated with this Command which must be closed first.

    Например, вот в таком месте:

    @model IEnumerable<Shop>
    @{
        var shops = Model;
    }

    я дописываю в конце присваивания .ToList() и ошибка пропадает - что делать, как с этим жить?

    18 июня 2012 г. 11:54

Ответы

Все ответы

  • Думаю модератор перенесёт топик в раздел веб. При использовании типа IEnumerable используется отложенна загрузка, и судя по предоставленным данным поток чтения закрывается преждевременно или данные читаются долго. При вызове метода ToList() отложенаая загрузка не используется, и данные загружаются разом. Покажите код модели и контроллера, как Вы именно получаете их. А то сказать что-либо конкретно по предоставленным данным невозможно.
    18 июня 2012 г. 18:41
    Модератор
  • решил так - добавил "MultipleActiveResultSets=True" в connectionString
    19 июня 2012 г. 6:36
  • Да, может это и выход, но не решение. В дальнейшем могут быть проблемы.
    19 июня 2012 г. 6:54
    Модератор
  • С производительностью например или с параллельным выполнением комманд. Ещё сказать что-либо трудно, не зная что там у Вас на самом деле присходит. Хотя если у Вас приложение "маленькое" то беспокоиться незачем.
    19 июня 2012 г. 7:06
    Модератор
  • лан, буду иметь ввиду

    с производительностью решение, допустим, понятно - можно физических ресурсов добавить, а с параллельностью что - будет медленно работать или падать? 

    что там происходит, да ничего не происходит, обычные разделы, допустим вот такая въюха

    @model IEnumerable<Floor>
    @{
    	var floors = Model;
    }
    
    @if (floors != null && floors.Count() > 0)
    {
    	foreach (var floor_l in floors)
    	{
    		 <script type="text/javascript">
    			$(function () {
    			   $('[floorid="@floor_l.Id"]').addClass('active');
    			});
    		</script>
    	<div style="background: url('@floor_l.ImageUrl') no-repeat;" class="floor_schema">
    		<img src="/Content/img/blank.gif" width="652" height="503" border="0" usemap="#floore@(floor_l.Id)" id="floor_area_img" />
    		<map name="floore@(floor_l.Id)">
    		@foreach (var shopfloor in floor_l.ShopFloors)
    		{
    			if (shopfloor.left != null && shopfloor.top != null && !string.IsNullOrEmpty(shopfloor.Shop.Coords))
    			{
    				int left = Convert.ToInt32(Math.Ceiling(Decimal.Parse(shopfloor.left, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)));
    				int top = Convert.ToInt32(Math.Ceiling(Decimal.Parse(shopfloor.top, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)));
    
    				<area pathid="#idshop@(shopfloor.ShopId)" shape="poly" coords="@(shopfloor.Shop.Coords)" href="/Shop/@shopfloor.Shop.Url" />
    
    			}
    		}
    		</map>
    		@foreach (var shopfloor in floor_l.ShopFloors)
    		{
    
    			if (shopfloor.left != null && shopfloor.top != null)
    			{
    				int left = Convert.ToInt32(Math.Ceiling(Decimal.Parse(shopfloor.left, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)));
    				int top = Convert.ToInt32(Math.Ceiling(Decimal.Parse(shopfloor.top, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)));
    			 
    			<div id="idshop@(shopfloor.ShopId)" class="@shopfloor.ShopId popupfloor mark" style="left: @(left)px; top: @(top - 30)px;display:none">
    			@if (shopfloor.Shop.TableName == "Atm")
    			{
    			 <span> @shopfloor.Title</span>
    			}
    			else
    			{
    			 <a href="/Shop/@shopfloor.Shop.Url"> @shopfloor.Title</a>
    			}
    			
    
    			</div>
    			<div id="idshop@(shopfloor.ShopId)mark" class="@shopfloor.ShopId mark" style="position: absolute; display: block; width: 10px; height: 10px; left: @(left)px; top: @(top)px;display:none">
    				<img src="/Content/img/marker.png" />
    			</div>
    			}
    		}
    	</div>
    	}
    
    	}

    19 июня 2012 г. 7:11
  • "с производительностью решение, допустим, понятно - можно физических ресурсов добавить" - зачем, если всё программно можно сделать. И потом бывают такие баги, что и ресурсы не помогают.

    "а с параллельностью что - будет медленно работать или падать? " - и то и другое, в зависимости от того что делает ваше приложение. Почитайте, там в нижней части.

    "обычные разделы" у одного из наших форумчан тоже обычный код был, а приложение падало при 50 пользователях. "допустим вот такая въюха" - а он не сильно интересен в данном контексте, гораздо интереснее код модели.

    19 июня 2012 г. 12:13
    Модератор
  • У Вас внутри IEnumerable скрывается IQueryable (linq запрос, наверное или EF). От него в данном случае лучше получить данные полностью, тем самым закрыв datareader. Собственно, это Вы и делаете с помощью ToList(). Совершенно правильный вызов, по-моему. Неясны Ваши опасения по поводу ToList()

    22 июня 2012 г. 6:34
  • Уважаемый пользователь не бросайте топик без ответа. Если хотите разобраться в проблеме,то приведите код модели, а если"MultipleActiveResultSets=True" для Вас решение, то добавить тогда нечего.
    26 июня 2012 г. 17:54
    Модератор
  • да вроде же разобрались - нефиг кучу обращений к контексту заводить, вот код модели

    [GET("Shops/{type}")]
                    public ActionResult ShopFloorNew(string type, int catId = 0)
                    {
                            BreadCrumbs.Add("магазины", "");
                            ViewBag.BreadCrumbs = BreadCrumbs;
                            type = string.IsNullOrEmpty(type) ? "ShopList" : type;
                            if (type == "ShopSchema")
                            {
                                    ViewBag.Floors = Db.Floors;
                                    ViewBag.GoodsCategories = Db.GoodsCategories.ToList();
                            }
                            var shops = Db.Shops.Published().Where(t => t.TableName == "Shop" && (catId == 0 || t.GoodsCategories.Any(c => c.Id == catId))).OrderBy(t => t.Title).ToList();
                            ViewBag.Type = "abc";
                            return View(type, shops);
                    }

    27 июня 2012 г. 7:25
  • Код у Вас, мяго говоря, жуткий, и это код контроллера, модель у Вас - то, что работает с БД, насколько я понял используете ORM. Старайтесь использовать один объект модели и передавать его в представление. Это намного облегчит возможность тестирования и сопровождения в дальнейшем. У Вас я их насчитал целых четыре: ViewBag.BreadCrumbs, ViewBag.Floors, ViewBag.GoodsCategories,shops. Используйте так называемые view model и шаблон репозиторий.

    var shops = Db.Shops.Published().Where(t => t.TableName == "Shop" && (catId == 0 || t.GoodsCategories.Any(c => c.Id == catId))).OrderBy(t => t.Title).ToList();

    Эту работу у Вас должен делать репозиторий(реализация в модели), контроллер должен передавать лишь результат в представление. Вообщем много чего можно сказать, не будем растягивать тему, всё дело техники и времени. Будем считать, что тема закрыта.

    27 июня 2012 г. 7:57
    Модератор
  • да, используется Entity Framework, этот код мне достался по наследству, теоретически я знаю про такую штуку как ViewModel, но честно говоря, не горю желанием все это переделывать и заводить новые ViewModel для каждой страницы, потом их заполнять, потом потрошить...
    27 июня 2012 г. 8:04