如何将实体框架(代码优先)与动态创建的连接字符串和单文件数据库一起使用?

Posted

技术标签:

【中文标题】如何将实体框架(代码优先)与动态创建的连接字符串和单文件数据库一起使用?【英文标题】:How to use entity framework (code first) with a dynamic created connection string and a single-file database? 【发布时间】:2011-09-17 19:20:30 【问题描述】:

我正在使用 SqlServerCompact,具有代码优先的实体框架,并且我正在动态生成连接字符串,因为它是在用户请求时生成的数据库。

我遵循了这个问题的建议:How do I programmatically set the connection string for Entity-Framework Code-First? 但是,我仍然有问题,事实上我收到一个异常,抱怨模型中的架构与代码中使用的不同。

这很明显,但是我希望从代码生成架构,所以我真的不明白为什么会发生这种情况

有人可以帮助我吗?这里是使用的代码:

NerdDinners.cs

class NerdDinners : DbContext

    public static string CreateConnectionString(string dbPath = @"|DataDirectory|\NerdDinners.sdf")
    
        SqlCeConnectionStringBuilder sqlConnection = new SqlCeConnectionStringBuilder();
        sqlConnection.Password = "9023fase93";
        sqlConnection.DataSource = dbPath;

        EntityConnectionStringBuilder connection = new EntityConnectionStringBuilder();
        connection.Metadata = @"res://*/NerdDinnersModel.csdl|res://*/NerdDinnersModel.ssdl|res://*/NerdDinnersModel.msl";
        connection.Provider = "System.Data.SqlServerCe.3.5";
        connection.ProviderConnectionString = sqlConnection.ToString();

        return connection.ToString();
    

    public NerdDinners() : base()  
    public NerdDinners(string nameOrConnectionString) : base(nameOrConnectionString)  

    public DbSet<Dinner> Dinners  get; set; 
    public DbSet<RSVP> RSVPs  get; set; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        Database.SetInitializer<NerdDinners>(new NerdDinnersInitializer());
        Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe");

        base.OnModelCreating(modelBuilder);
    

Program.cs

class Program

    static void Main(string[] args)
    
        NerdDinners nerdDinner = new NerdDinners(NerdDinners.CreateConnectionString());
        Console.WriteLine("Inizio test");

        var res = from d in nerdDinner.Dinners
                  select d;

        Console.WriteLine("Dinners:");
        foreach (var item in res)
            Console.WriteLine(item.ToString());
        Console.WriteLine("End");

        // Usato per terminazione
        Console.ReadKey();
    

这是我的解决方案(图片):

编辑 1:

错误是 MetadataException,它抱怨架构无效

编辑 2:

NerdDinnersInitializer.cs

class NerdDinnersInitializer : DropCreateDatabaseAlways<NerdDinners>

    public NerdDinnersInitializer() : base()  

    protected override void Seed(NerdDinners context)
    
        var toadd = new List<Dinner>
        
            new Dinner
            
                Address = "bla",
                DinnerID = 0,
                EventDate = DateTime.Parse("2010-12-03"),
                HostedBy = "mclink",
                Title = "Notitle",
            ,
            new Dinner
            
                Address = "Fiwe",
                DinnerID = 0,
                EventDate = DateTime.Parse("2011-12-03"),
                HostedBy = "ngi",
                Title = "Bah",
            ,
        ;

        toadd.ForEach(item => context.Dinners.Add(item));

        context.SaveChanges();

        base.Seed(context);
    

【问题讨论】:

【参考方案1】:

我不确定这是否适用于您的情况,但如果模型与当前现有的数据库架构不匹配,您可能会收到错误消息。你需要做类似的事情-

Database.SetInitializer<NerdDinners>(
    new DropCreateDatabaseIfModelChanges<NerdDinners>());

这将删除现有数据库并根据您的模型创建一个新数据库。

您的示例代码中确实有一些设置初始化程序的代码 -

Database.SetInitializer<NerdDinners>(new NerdDinnersInitializer());

但我不确定您的 NerdDinnersInitializer 班级在做什么。

【讨论】:

你是对的对不起,但是它 NerdDinnersInitializer 直接继承自 DropCreateDatabaseIfModelChanges【参考方案2】:

我通过深度谷歌搜索找到了答案。 我理解我误解了代码优先的工作原理,事实上,如果您使用 code-first,您无法创建要连接的数据库

我仍然不明白您是否可以将使用代码优先生成的数据库保存在选定的位置(我认为您不能)。

但是,如果您想连接到现有的数据库文件,您必须使用模型优先或数据库优先的方法您不能先使用代码

这是我的理解,希望我没有错。 这个问题更好地解释了它:Why does Entity Framework Code-First (with an existing DB) keep trying get data from an EdmMetadata table?

编辑 1: 看起来我错了,有可能,但你需要 SQL Server compact 4.0 而不是 3.5(我遇到了问题),你还需要 vs 2010 和实体框架 4.1。 然后,只需按照这个问题的答案来动态创建字符串:Is possible to create a database (Sql Server compact) on a given path if we use Entity framework with code-first approach?

【讨论】:

你可以先用代码创建一个数据库,按照conentions:erikej.blogspot.com/2011/04/… 有了你的教程,我几乎在那里,现在我设法在没有 Model.edmx 的情况下连接到数据库(它之前要求它),链接没有'不解释,是如何使用动态生成的连接字符串。我需要这个,因为我必须动态地指定数据源(可以更改)。有什么建议吗?我解决了动态连接的问题; ***.com/questions/7458513/…

以上是关于如何将实体框架(代码优先)与动态创建的连接字符串和单文件数据库一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

实体框架代码的动态连接字符串首先在运行时 EF6(mssql、mysql、oracle)中用于多个数据库提供程序

将连接字符串传递给代码优先的 DbContext

orm 实体框架 4 和代码优先

在实体框架代码优先中,为啥我不能在连接字符串中使用 SQL Server Express?

MVC 代码优先 - 数据库未生成

实体框架代码优先 MaxLength 和 FixedLegth(char 与 varchar)