使用不同的静态值获取数据

时间:2013-08-09 15:28:10

标签: c# entity-framework

我目前的申请中存在以下问题。 (类示例应理解为实体框架实体类。)

让我们假设您有一个包含某些属性的静态类,这些属性在应用程序的Get / Set属性中用作应用程序范围的示例。

每次请求此属性时都会调用属性的Get,并通过数据绑定到某个控件,每当控件重绘(布局刷新)时都会发生这种情况。

现在我面临的问题是可能出现这种情况,我希望打开两个不同“静态”值的窗口,这是实现这种情况的最佳方式吗?

这里的一些代码可能会让事情变得更容易理解:

静态类,包含查询中使用的属性:

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

在属性Name:

的get / set中使用Core.IdLang的类
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个不同的窗口中有2个DataGrids,并希望绑定两种不同语言的汽车列表。

我正在执行以下操作(仅针对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.IdLang现在有这个值,一旦在任一个Window上调用Get / Set,你只能接收或改变这种语言,而不是窗户。

在现实生活中,Core类将包含大约6个(或更多)属性,这些属性在50多个类中使用,这些属性都具有至少一个具有相同get / set代码的属性,您可以将其视为Car。姓名样本。

这些类中的任何一个都可以在提供的场景中使用,我希望将英语和德语数据显示在彼此旁边以进行比较。

2 个答案:

答案 0 :(得分:0)

这是非常脆弱的代码,因为您在Core类中的Car上有外部依赖项。如果您希望所有类自动拥有IdLang,那么您应该使用继承来实现它。否则,您可以使用Dependency Injection并通过Core构造函数将Car作为参数传递。

就个人而言,我认为完全没有使用Core课程。您可以将这两个属性IdLang和Company放入Car并通过构造函数初始化它们。

答案 1 :(得分:0)

基于你想要拥有不同的价值观,我会问:“你为什么要首先强制使用静态类?”。大多数情况下,在处理实体框架时,您可以获得一个T4生成器来为您创建POCO(普通旧类对象)并与之相关。但是,如果您想为不同语言创建一个显式保存属性的次级,为什么不保留“Car”对象,因为它在顶部定义但删除了Core Linq语句?

除非用户输入的值不正确,否则我不会从示例中得到什么。如果必须由于数据库外键约束,您可以单独添加验证方法。但是为什么不限制一个用户可以选择使用组合框或其他选项进行首选?然后你有一个蓝图,你可以保留在不同情况下重用,甚至把它放在构造函数中。我下面的例子很明确,但你可以把我的逻辑放在其他事件方法中。我尝试保持属性get和设置非常基本,并在其他部分进行验证。这样他们恕我直言的打字更好,并且与他们将会传递的内容相比更少混淆。 EG:

编辑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();

    }
}

现在我的例子中的关键是我选择了所有的汽车或特定的汽车。您可以轻松地将返回更改为List并返回语言为一对多关系的汽车列表,然后只过滤它。我只是想表明你可以在不同的时间返回一个非静态类的单个对象。通常,除非您需要某个与数据库不同的条件类的存储库来跟踪数据库之外的内容并且仅针对应用程序,否则无需更多POCO。如果它们存在于像MVM模式之类的ViewModel这样的UI的查看平台上。但是,对于仅使用数据库中的确切填充网格,不需要创建新类IMHO。您只需要保留在类中的返回方法,该类可以在命令上调用命令时调用。

通过上面的例子,如果你想申请一个网格,我相信你可能只是做到了

GetData d = new GetData();

var items = d.returnEntities();

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