Каково поведение динамического атрибута в статическом (расширенном) классе в C # (MVC3) - PullRequest
1 голос
/ 29 января 2012

Я новичок в разработке на .NET и C #, но долгое время работал с C, C ++, Java, PHP и т. Д.

У меня есть класс расширения MVC3 для моих моделей данных, который ссылается на базу данных. В классе он установлен как «приватная статика», но я думаю, что он не поспевает за изменениями в базе данных. Другими словами, когда я изменяю данные в контроллерах, эти изменения не «замечаются» в БД, потому что они статичны. В настоящее время я создаю и располагаю переменную для каждого использования, чтобы компенсировать это.

Мои вопросы:

  1. Правильно ли, что статическая переменная БД может вести себя таким образом?
  2. Нужно ли удалять динамическую переменную в статическом классе или сборщик мусора все равно позаботится об этом автоматически?

Вот соответствующий фрагмент класса:

namespace PBA.Models {
    using System;
    using System.Text.RegularExpressions;
    using PBA.Models;
    using PBA.Controllers;

    public static class Extensions {
        private static PbaDbEntities db = null;

        public static PbaDbEntities GetDb() {
            // TODO: find out about static memory/disposal, etc.
            //
            if (db != null) {
                db.Dispose();
            }
            db = new PbaDbEntities();
            return db;
        }

        public static string GetCheckpointState(this Activity activity, long memberProjectId) {
            GetDb();  // TODO: Do I need to do this each time, or will a one-time setting work?

            string state = CheckpointController.CHECKPOINT_STATUS_NOT_STARTED;
            try {
                var sub = db.ActivitySubmissions.
                    Where(s => s.activityId == activity.activityId).
                    Where(s => s.memberProjectId == memberProjectId).
                    OrderByDescending(s => s.submitted).
                    First();
                if (sub != null) {
                    state = sub.checkpointStatusId;
                }
            }
            catch (Exception e) {
// omitted for brevity
                }
                return state;
            }
        }
    }

Ответы [ 4 ]

2 голосов
/ 29 января 2012

Ваш код ужасно потерпит неудачу в работе.
DataContexts не являются поточно-ориентированными;вы не должны совместно использовать контекст между запросами.

Никогда не помещайте изменяемые объекты в статические поля в многопоточных приложениях.

0 голосов
/ 29 января 2012

У меня нет никакого представления о контексте - если db - просто объект, похожий на соединение, или нет, но, похоже, вы выбрасываете и воссоздаете все, что излишне.

Лучше всего создать свойство (независимо от того, что вы делаете), чтобы быть последовательным.

private static Thing _thing;
private static Thing thing{
  get{
    if(_thing==null){
      _thing=new Thing();
    }
    return _thing;
  }
}
0 голосов
/ 29 января 2012

Похоже, вам нужно прочитать о mvc3 и средах управления объектами, прежде чем писать кодирование и просить здесь о помощи по чему-то, что закодировано с использованием дурных практик.

Отвечая на ваши вопросы:

1- нет

2- не имеет смысла, поскольку ответ на 1

Сделайте все правильно, вот некоторая полезная документация: http://msdn.microsoft.com/en-us/library/ie/gg416514(v=vs.98).aspx

РЕДАКТИРОВАТЬ: Добавление некоторого явного исправления

Вы можете получить доступ к своему dbcontext из статического класса, например, так:

var context = DbProvider.CurrentDb;

Идея состоит в том, чтобы обращаться к вашей БД отсюда всегда: из ваших методов расширения и из действий вашего контроллера.

Тогда реализация DbProvider.CurrentDb будет выглядеть примерно так:

public static classDbProvider {

    public static void Initialize(){
        HttpContext.Current.ApplicationInstance.BeginRequest += CreateDb;
        HttpConetxt.Current.ApplicationInstance.EndRequest += DisposeDb;
    }

    private static void CreateDb(object sender, EventArgs e) {
        HttpContext.Items.Add("CurrentDb", new PbaDbEntities(););
    }

    private static void DisposeDb(object sender, EventArgs e)
    {
        Current.Dispose();
        HttpContext.Items.Remove("CurrentDb");
    }

    public static PbaDbEntities CurrentDb{
        get {
            return (PbaDbEntities)HttpContext.Current.Items["CurrentDb"];
        }
    }
}

Как вы можете видеть, он будет создавать новый Db для каждого запроса, и он будет доступен ТОЛЬКО в этом запросе.Таким образом, ваша БД будет располагаться в конце каждого запроса.Этот шаблон называется Open-Session-in-View.

Наконец, вам нужно инициализировать DbProvider, вызывающий метод Initialize() в вашем файле Global.asax, в событии Application_start.

Надеюсь, это поможет.

0 голосов
/ 29 января 2012

Игнорировать исключения таким образом - ужасная идея, если вы не хотите обрабатывать исключения, просто не пытайтесь / ловить, или ловить и перебрасывать.Подумайте об этом так, после того как вы спрятали исключение, ваша программа находится в недопустимом состоянии, потому что вы не можете контролировать ошибку.Теперь, когда вы скрыли исключение, ваша программа может продолжать работать, но она в плохом состоянии.

Если ваш код поступит в производство, через 3,5 года будет немного младше.Программист собирается принять участие в какой-то середине ночного огненного шторма, потому что внезапно сайт сломался, хотя раньше он работал.Будет совершенно невозможно отследить, где происходит исключение, поэтому этот бедняга потратит 48 часов подряд, добавляя регистрационный код повсеместно, чтобы отследить проблему.Он обнаружит, что какой-то администратор баз данных где-то решил переименовать столбец MemberProjectId в MemberProjectIdentifier, что вызвало взрыв вашего linq.

Думайте о детях, обрабатывайте исключения, не хороните их.

Кстати, да, я был тем парнем, который должен выяснить эти типы ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...