2013-08-09 2 views
0

У меня есть следующая проблема в моем текущем приложении. (К классу следует понимать классы Entity Framework Entity.)Получение данных с различными статическими значениями

Предполагается, что у вас есть статический класс, содержащий некоторые свойства, которые широко используются в качестве примера в variaous Get/Set of properties.

Get the property вызывается каждый раз, когда вы запрашиваете это свойство, с привязкой данных к некоторому управлению, которое это возможно происходит каждый раз, когда есть перерисовывание (обновление макета) элемента управления.

Теперь я столкнулся с проблемой, что может возникнуть ситуация, когда я хочу открыть 2 окна с разными «статическими» значениями, каков наилучший способ достичь этого сценария?

Вот код, который может быть, делает вещи проще понять:

Статический класс, придерживая свойства, которые используются в запросах:

public static class Core 
{ 
    public string IdLang { get; set; } 
    public string IdCompany { get; set; } 
} 

Класс, который использует Core.IdLang в GET/набор недвижимости Название:

public class Car 
{ 
    private string _name; 
    public string Name 
    { 
     get 
     { 
      _name = (from x in LanguageTables 
        where x.IdLang == Core.IdLang 
        select x.Text).FirstOrDefault(); 

      return _name; 
     } 
     set 
     { 
      if (value == _name) 
       return; 

      var languageTable = (from x in LanguageTables 
           where x.IdLang == Core.IdLang 
           select x).FirstOrDefault(); 

      if (languageTable == null) 
      { 
       languageTable = new LanguageTable(); 
       languageTable.IdLang = Core.IdLang; 
      } 

      languageTable.Text = _name; 
     } 
    } 
} 

Теперь предположим, у вас есть 2 DataGrids в 2-х разных окнах и хотите связать список автомобилей с двумя различными языками.

Я делаю следующее (пример только для 1 сетки и окна):

public class Window1 : Window 
{ 
    List<Car> Cars; 
    public Window1() 
    { 
     InitializeComponents(); 
     Core.IdLang = "DE"; 

     Cars = new List<Car>();    

     //fetch data from Database, and populate the List<Car> 

     Grid1.ItemsSource = from x in Cars 
          select x; 
    } 
} 

Теперь просто думать о копировании и вставке этот код выше (window1) и есть второе окно и хотите, чтобы отобразить все автомобили с их английскими именами, поэтому я изменил следующий код:

Core.IdLang = "DE"; 

к

Core.IdLang = "EN"; 

И думал, что все сработает, но то, что когда-либо Window вы называете позже, Core.IdLang теперь имеет это значение, и как только Get/Set вызывается в любом Окне, вы будете получать или изменять его только на этом языке, а не иначе между окнами ,

В реальном приложении класс Core будет состоять из около 6 (или более) свойств, которые используются в более чем 50 классах, все из которых имеют минимум одно свойство, имеющее тот же код get/set, что и вы, .Имя образца.

Любой из этих классов может использоваться в предоставленном сценарии, где я хотел бы показывать английские и немецкие данные рядом друг с другом для сравнения.

+0

Если они изменяются для каждого экземпляра, который использует его, 'Core' не должен быть статическим классом, а скорее классом, который имеет свойства, которые имеют значения по умолчанию. –

ответ

0

Основываясь на желании иметь разные значения, я бы спросил: «Почему вы в первую очередь ставите статический класс?». В большинстве случаев, когда вы работаете с Entity Framework, вы можете получить генератор T4, чтобы сделать POCO (Обычные объекты старого класса) для вас, и вы относитесь к ним. Однако, если вы хотите сделать вторичный уровень явного владения свойствами для разных языков, почему бы не просто сохранить свой объект «Автомобиль», как он определен сверху, а удалить операторы Core Linq?

Я не получаю от примера то, что для вас значит, за исключением случаев, когда пользователь вводит неправильное значение. Вы всегда можете добавить метод проверки отдельно, если это необходимо из-за ограничений внешнего ключа базы данных. Но почему бы не ограничить набор, который пользователь может выбрать с помощью combobox или другого для их выбора в первую очередь? Тогда у вас есть план, который вы можете сохранить для повторного использования для разных обстоятельств или даже поместить его в конструктор. Мой пример ниже довольно явный, но вы можете взять мою логику и поместить ее в другие методы событий. Я стараюсь, чтобы свойства получили и устанавливали довольно простые и выполняли валидацию другими частями. Таким образом они ИМХО более хорошо набраны, и есть меньше путаницы с проходом с тем, чем они будут. EG:

EDIT 8-11-13, чтобы быть более точным

// I am the generated POCO form the Entity Model 
public class Car 
{ 
    public string IdLang { get; set; } 
    public string IdCompany { get; set; } 
} 

// I am a class for just 'get' methods or update methods potentially 
public class GetData 
{ 
    // I am returning a single Entity of 'Car' type based on predicate 
    public Car returnSpecificCar(string aLanguage) 
    { 
     using (EntityName e = new EntityName()) 
     { 
      // I like lambda methods better due to less lines 
      return e.Car.FirstOrDefault(n => n.Language == aLanguage); 

      // Similar method in Linq style 
      // return (from c in e.Car where c.Language == aLanguage 
      // select c).FirstOrDefault(); 
     } 
    } 

    // I return all cars 
    public List<Car> returnAllCars() 
    { 
     using (EntityName e = new EntityName()) 
     { 
      return e.Car.ToList(); 
     } 
    } 
} 

// Simple console example 
class Program 
{ 
    static void Main(string[] arts) 
    { 
     GetData d = new GetData(); 

     var cars = d.returnEntites(); 
     var specCar1 = d.returnSpecificCar("EN"); 
     var specCar2 = d.returnSpecificCar("DE"); 

     string ln = "-----All cars----" + Environment.NewLine; 

     cars.ForEach(c => ln += c.CarId + "\t" + c.CarName + Environment.NewLine); 

     ln += Environment.NewLine + Environment.NewLine + "----Specific Car1 -----" + Environment.NewLine; 

     ln += specCar1.CarID + "\t" + specCar1.CarName+ Environment.NewLine; 

     ln += Environment.NewLine + Environment.NewLine + "----Specific Car2 -----" + Environment.NewLine; 

     ln += specCar2.CarID + "\t" + specCar2.CarName + Environment.NewLine; 

     Console.WriteLine(ln); 

     Console.ReadLine(); 

    } 
} 

Теперь ключ в моем примере, что я решил дать все автомобили или конкретный автомобиль. Вы можете легко изменить возврат в список и вернуть список автомобилей, где язык является отношением один к другому, а затем просто фильтровать его. Я просто хотел показать, что вы можете возвращать один объект за раз DIFFERENTLY с нестационарным классом. Как правило, если вам не нужен репозиторий определенного условного класса, который отличается от вашей базы данных, чтобы отслеживать вещи за пределами вашей базы данных и только для приложения, нет необходимости делать больше POCO. Если они существуют для платформы просмотра для пользовательского интерфейса, такого как ViewModel, возможно, после шаблона MVVM. Но для простого заполнения сетки именно тем, что находится в базе данных, нет необходимости создавать новый класс IMHO. Вам просто нужны методы возврата, хранящиеся в классе, которые могут быть вызваны командой, которые изменяются по команде.

В примере выше, если вы хотите применить к сетке, я считаю, с верхней части моей головы, вы можете просто сделать

GetData d = new GetData(); 

var items = d.returnEntities(); 

// Assumes your grid itemname is 'grid' 
grid.ItemsSource = items; 
+0

Как вы, возможно, знаете, Entity Framework всегда создает экземпляры объектов, которые бросают пустой конструктор. Поэтому позвольте предположить, что вы вызываете следующий запрос LINQ. из автомобиля в Entities.Cars выбрать автомобиль. Автомобили с DbSet , предоставленные Entity Framework, как бы написать код или сообщить Entity Framework заполнить DbSet моим конструктором и моими параметрами? –

+0

Сущность - это только класс объектов-контейнеров. Заменить список со списком <(entitycreatedPOCO)>. Как правило, с Entity Version 5 это делает его очень простым. Вам просто нужно следить за свойствами. Поэтому, если бы Car был таблицей, у нее было бы две колонки. Для заполнения вам будет просто объявлен контейнер (EntityPOCO) = New (EntityPOCO) {(Column1) = (значение, которое вы ввели), (Column2) = (следующее значение, которое вы ввели)} '. – djangojazz

+0

Но снова вы создаете новые автомобили с указанными значениями, я хочу получить данные из базы данных (например, Entity Framework) и просто расширить созданные классы с помощью настраиваемых свойств. Итак, как получить из базы данных и в то же время инициализировать мои автомобили с помощью специального конструктора? –

0

Это очень хрупкий код, потому что у вас есть внешние зависимости от Core в пределах вашего класса Car. Если вы хотите, чтобы все ваши классы имели IdLang автоматически, вы должны использовать наследование для его достижения. В противном случае вы можете использовать Dependency Injection и просто передать Core в качестве параметра через конструктор Car.

Лично я не вижу смысла в классе Core. Вы можете удалить эти два свойства IdLang и Company в Car и инициализировать их через конструктор.

Смежные вопросы