Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我应该如何用实体框架对静态参考数据建模?_C#_Entity Framework_Oop_Design Patterns_Data Modeling - Fatal编程技术网

C# 我应该如何用实体框架对静态参考数据建模?

C# 我应该如何用实体框架对静态参考数据建模?,c#,entity-framework,oop,design-patterns,data-modeling,C#,Entity Framework,Oop,Design Patterns,Data Modeling,我有一个仿真模型,它使用一个数据库来存储输入和输出数据,使用实体框架和数据库优先的方法。通过数据访问层查询数据库,大致如下所述: 但是,使用的一些静态输入数据并没有存储在数据库中,而是作为字段硬编码到应用程序中。此数据是真正静态的,在应用程序运行时不会更改。例如: public class Currency { public string Symbol { get; private set; } public string Name { get; private set; }

我有一个仿真模型,它使用一个数据库来存储输入和输出数据,使用实体框架和数据库优先的方法。通过数据访问层查询数据库,大致如下所述:

但是,使用的一些静态输入数据并没有存储在数据库中,而是作为字段硬编码到应用程序中。此数据是真正静态的,在应用程序运行时不会更改。例如:

public class Currency
{
    public string Symbol { get; private set; }
    public string Name { get; private set; }

    private Currency()
    {
    }

    // Fields like this store reference data
    public static readonly Currency USD = new Currency
    {
        Symbol = "USD",
        Name = "US Dollar"
    };

    public static readonly Currency EUR = new Currency
    {
        Symbol = "EUR",
        Name = "Euro"
    };
}
这样做的优点是,参考参考数据与在整个模型中使用例如
Currency.USD
一样容易,而不必经过数据访问层。这种实现方式的缺点是,数据模型很笨拙,不再是真正的关系模型(在通过外键强制关系的意义上);使用上述参考数据的模型对象,如

public class Transaction
{
    public int Id { get; set; }
    public Currency Currency { get; set; }
    public double Price { get; set; }
}
在数据库中有一个如下所示的备份表:

create table Transaction
(
    Id int not null primary key,
    Currency nvarchar(3) not null , -- Currency symbol, not a foreign key
    Price float not null 
);
在通过业务层读写时,currency属性在字符串和对象之间来回转换

我想用以下目标改写这篇文章:

  • 将静态参考数据与所有其他数据一起存储在数据库中,以保持数据模型干净
  • 不必在每次需要静态参考数据时查询数据访问层(即,尽可能接近硬编码的
    货币.USD
    )。在整个模拟运行过程中,参考数据可能在启动时读取一次,然后查询100000000次
我在这里寻找的是某种缓存机制吗?这可能足够吗?一般来说,哪种优雅的方法可以解决这个问题,尤其是实体框架


谢谢。

以下是使用EF执行此操作的模式:

本例中的静态引用数据“Color”具有非int键和额外属性。这两个都是枚举无法完成的。它使用初始值设定项将引用数据添加到数据库中,但首先在数据库中,您只需提前添加它,并假设它在那里

此模式的一个变体将使用启动时从数据库检索的引用实体的惰性静态集合,而不是在类定义中硬编码值。无论哪种情况,在SaveChanges中将引用实体标记为未更改都会阻止EF尝试将它们插入数据库

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;

namespace Ef6Test
{

    public class Color
    {
        public static Color Red = new Color() { Name = "Red", RGB = 0xFF0000 };
        public static Color Green = new Color() { Name = "Green", RGB = 0x00FF00 };
        public static Color Blue = new Color() { Name = "Blue", RGB = 0x0000FF };
        [Key]
        public string Name { get; set; }
        public int RGB { get; set; }
    }

    public class Car
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public string ColorName { get; set; }
        public Color Color { get; set; }
    }

    class Db : DbContext
    {

        public DbSet<Color> Colors { get; set; }
        public DbSet<Car> Cars { get; set; }


        public override int SaveChanges()
        {
            return SaveChanges(false);
        }
        public int SaveChanges(bool includeStatic = false)
        {
            if (!includeStatic)
            {
                foreach (var e in ChangeTracker.Entries<Color>())
                {
                    e.State = EntityState.Unchanged;
                }
            }

            return base.SaveChanges();
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
    }

    class MyInitializer : DropCreateDatabaseAlways<Db>
    {
        protected override void Seed(Db context)
        {
            base.Seed(context);
            context.Colors.AddRange(new[] {Color.Red,Color.Green,Color.Blue });
            context.SaveChanges(true);

        }
    }

    class Program
    {    
        static void Main(string[] args)
        {    
            Database.SetInitializer(new MyInitializer());

            using (var db = new Db())
            {
                db.Database.Log = m => Console.WriteLine(m);
                db.Database.Initialize(true);
            }
            using (var db = new Db())
            {
                db.Database.Log = m => Console.WriteLine(m);

                var c = db.Cars.Create();
                c.Color = Color.Red;
                db.Cars.Add(c);

                db.SaveChanges();

            }


            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.ComponentModel.DataAnnotations;
使用System.ComponentModel.DataAnnotations.Schema;
使用System.Data.Entity;
使用System.Linq;
命名空间Ef6Test
{
公共类颜色
{
公共静态颜色Red=new Color(){Name=“Red”,RGB=0xFF0000};
公共静态颜色绿色=新颜色(){Name=“绿色”,RGB=0x00FF00};
公共静态颜色Blue=new Color(){Name=“Blue”,RGB=0x0000FF};
[关键]
公共字符串名称{get;set;}
公共整数RGB{get;set;}
}
公车
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串ColorName{get;set;}
公共颜色{get;set;}
}
类Db:DbContext
{
公共数据库集颜色{get;set;}
公共数据库集车辆{get;set;}
公共覆盖int SaveChanges()
{
返回SaveChanges(false);
}
public int SaveChanges(bool includeStatic=false)
{
如果(!includeStatic)
{
foreach(ChangeTracker.Entries()中的变量e)
{
e、 状态=实体状态。未更改;
}
}
返回base.SaveChanges();
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
基于模型创建(modelBuilder);
}
}
类MyInitializer:DropCreateDatabaseAlways
{
受保护的覆盖无效种子(Db上下文)
{
种子(上下文);
context.Colors.AddRange(新[]{Color.Red,Color.Green,Color.Blue});
context.SaveChanges(true);
}
}
班级计划
{    
静态void Main(字符串[]参数)
{    
SetInitializer(新的MyInitializer());
使用(var db=new db())
{
db.Database.Log=m=>Console.WriteLine(m);
db.Database.Initialize(true);
}
使用(var db=new db())
{
db.Database.Log=m=>Console.WriteLine(m);
var c=db.Cars.Create();
c、 颜色=颜色。红色;
db.Cars.添加(c);
db.SaveChanges();
}
Console.WriteLine(“按任意键退出”);
Console.ReadKey();
}
}
}

你认为Enums是谁?由于每个查找对象都有其名称以外的属性,因此仅使用枚举本身可能是不够的(除非我误解了本文,对VB不太熟悉)。但现在我想了想,我要找的基本上是一个带有属性的枚举,或者尽可能接近它的枚举。看看,它包含了关于如何在C#中获得类似java的枚举(带有属性)的答案。我认为这可能适合您与EF的关系,您可以通过缓存属性收集部分对其进行一些优化。此外,如果您仅使用2个属性,则symbol=value和name=description。这正是我们为货币所做的。我们可以根据需要引用任何一种。@RMH有趣的方法,我将测试类似的东西。我设想我们可以使用枚举来保存引用数据的标记(可以这么说),而实际数据(即其他所有数据)来自修饰每个枚举值的属性,并从数据库加载。不确定什么