在客户端机器上编程创建SQL Server Compact数据库

3
我最近开始尝试使用SQL Server Compact和EF6进行实验。我目前正在使用模型优先方法并从中生成我的类和表格。不过,我有一个疑问。如何让程序动态创建数据库?它在我的机器上存在,因为我使用了SQL Server Compact/SQLite工具包来创建它,但是当程序部署到客户计算机时,需要创建数据库。
我想在第一次运行时提示用户选择一个良好的位置,然后创建整个DB架构并在将来使用它。我查看了this guide,但VS开始抱怨它不起作用,因为我没有使用代码优先方法。
如果您需要更多信息,请告诉我!谢谢。

你可以使用SqlCeEngine.CreateDatabase创建一个空数据库,然后运行一个SQL脚本来创建所需的对象。 - ErikEJ
嗨,Erik!感谢您的出色工作!我假设您推荐这条路线是因为EF没有提供任何运行时数据库生成功能?我的意思是:是否有一种方法可以在运行时获取用于创建数据库的原始SQL,并将其用作您所提到的“SQL脚本”? - Matthew Goulart
1个回答

3
我正在使用SQL CE和EF开发一个小应用程序,并在应用程序安装(clickonce)时部署模板数据库。然后我在应用程序启动时使用闪屏界面,要么加载先前创建的数据库,要么让用户创建新的数据库。
当他们创建新的数据库时,我只需提示他们选择位置并将模板数据库复制到他们想要的位置并命名。我还设置了使用部署的数据库而不给他们多个数据库文件的机会。
我们需要处理以下几个部分:
1.SQL CE数据库文件
我的库存/模板.sdf文件位于项目文件夹中,并在Visual Studio中包含在项目中(我正在使用2015年版)。单击解决方案资源管理器中的文件,然后选择属性,您需要设置以下内容:
构建操作-内容 复制到输出目录-始终复制
2.创建全局变量
可以使用现有的模块文件或创建一个看起来像这样的新文件:
Public Module Globals

  Friend g_recipeData As RecipeEntities

End Module
  1. 创建最后文件路径的设置

在解决方案资源管理器中右键单击项目名称,选择属性。点击设置选项卡并添加以下新设置:

名称:lastpath
类型:字符串
范围:用户
值:

  1. 创建闪屏窗体(frmSplash)

我的闪屏窗体如下所示:

Splash Screen

窗体上的控件如下:

txtFile
cmdSelectDatabase
cmdNew
cmdOpen
cmdExit

  1. 闪屏窗体(frmSplash)代码

区域“窗体方法”

Private Sub OnFormLoad() Handles Me.Load

    txtFile.Text = My.Settings.lastpath

    If txtFile.Text <> "" Then
        cmdOpen.Enabled = True
        cmdOpen.Select()
    Else
        cmdNew.Select()
    End If

End Sub

Private Sub FileSelect()

    Try

        Dim openFileDialog As New OpenFileDialog()

        openFileDialog.Filter = "sdf files (*.sdf)|*.sdf|All files (*.*)|*.*"
        openFileDialog.FilterIndex = 1
        openFileDialog.RestoreDirectory = True

        Dim result As DialogResult = openFileDialog.ShowDialog(Me)

        If result = DialogResult.Cancel Then
            cmdSelectDatabase.Select()
            Exit Sub
        End If

        txtFile.Text = openFileDialog.FileName

        If txtFile.Text <> "" Then
            cmdOpen.Enabled = True
            cmdOpen.Select()
            My.Settings.lastpath = openFileDialog.FileName
            My.Settings.Save()
        Else
            cmdOpen.Enabled = False
            cmdSelectDatabase.Select()
        End If

    Catch ex As Exception

        MessageBox.Show(ex.Message.ToString, "Application Error")
        Application.Exit()

    Finally

    End Try

End Sub 

Private Sub SetConnectionString()

    Try

        Dim providerName As String = "System.Data.SqlServerCe.4.0"
        Dim datasource As String = txtFile.Text

        Dim sqlCeBuilder As New SqlCeConnectionStringBuilder

        sqlCeBuilder.DataSource = datasource
        sqlCeBuilder.PersistSecurityInfo = True

        g_SQLCeConnectionString = sqlCeBuilder.ConnectionString

        Dim providerString As String = sqlCeBuilder.ToString()

        Dim entityBuilder As New EntityConnectionStringBuilder()

        entityBuilder.Provider = providerName

        entityBuilder.ProviderConnectionString = providerString

        entityBuilder.Metadata = "res://*/RecipeModel.csdl|res://*/RecipeModel.ssdl|res://*/RecipeModel.msl"

        Dim c As System.Configuration.Configuration = ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location)
        Dim section As ConnectionStringsSection = DirectCast(c.GetSection("connectionStrings"), ConnectionStringsSection)

        g_EntityConnectionString = entityBuilder.ConnectionString

        section.ConnectionStrings("RecipeEntities").ConnectionString = g_EntityConnectionString
        c.Save(ConfigurationSaveMode.Modified)
        ConfigurationManager.RefreshSection("connectionStrings")

    Catch ex As Exception

        MessageBox.Show(ex.Message.ToString, "Application Error")
        Application.Exit()
    End Try

End Sub 

Private Sub CreateDatabase()

    Try
        Dim saveFileDialog As New SaveFileDialog()
        saveFileDialog.Filter = "sdf files (*.sdf)|*.sdf"
        saveFileDialog.Title = "Create Database"
        saveFileDialog.FilterIndex = 1

        If saveFileDialog.ShowDialog() = DialogResult.OK Then

            File.Copy(Path.Combine(ApplicationDeployment.CurrentDeployment.DataDirectory, "rw.sdf"), saveFileDialog.FileName, True)

            Dim strPathandFile As String = saveFileDialog.FileName

            txtFile.Text = strPathandFile
            My.Settings.lastpath = strPathandFile
            My.Settings.Save()

            cmdOpen.Enabled = True

        End If

    Catch ex As Exception

        MessageBox.Show(ex.Message.ToString, "Application Error")
        Application.Exit()
    End Try

End Sub

Private Sub LoadMainApplication()

    Try
        Dim objNewForm As New FrmMain
        objNewForm.Show()
        Me.Close()

    Catch ex As Exception

        MessageBox.Show(ex.Message.ToString, "Application Error")
        Application.Exit()
    End Try

End Sub

End Region

Region "Event Handlers"

Private Sub cmdSelectDatabase_Click(sender As Object,
                                    e As EventArgs) Handles cmdSelectDatabase.Click

    FileSelect()
    cmdOpen.Select()

End Sub


Private Sub cmdCancel_Click(sender As Object, e As EventArgs) Handles cmdExit.Click
    Me.Close()
End Sub


Private Sub cmdOk_Click(sender As Object, e As EventArgs) Handles cmdOpen.Click

    Me.Cursor = Cursors.WaitCursor

    SetConnectionString()
    LoadMainApplication()

    Me.Cursor = Cursors.Default

End Sub


Private Sub txtFile_Validated(sender As Object, e As EventArgs) Handles txtFile.Validated
    If txtFile.Text.Length = 0 Then
        cmdOpen.Enabled = False
    Else
        cmdOpen.Enabled = True
    End If
End Sub

Private Sub cmdNew_Click(sender As Object,
                         e As EventArgs) Handles cmdNew.Click
    CreateDatabase()
    SetConnectionString()
    LoadMainApplication()

End Sub

Private Sub CatchEnterKey(ByVal sender As Object,
    ByVal e As System.Windows.Forms.KeyPressEventArgs) _
        Handles txtFile.KeyPress, txtPassword.KeyPress


    If e.KeyChar = ChrW(Keys.Enter) Then
        cmdOk_Click(sender, e)
        e.Handled = True
        Exit Sub
    End If

End Sub
  1. 设置全局变量值

在您的主应用程序表单(如上所述的 frmMain)的构造函数中添加以下内容:

Public Sub New()

    InitializeComponent()
    g_recipeData = New RecipeEntities

End Sub

如果您在模块文件中创建变量时执行上述操作,则实体的连接字符串将被设置,并且您无法更改它。您必须首先在 app.config 中设置连接字符串(使用上述代码),然后在实例化时实体将使用所需的连接字符串。
我认为现在这就是基础知识了。我强烈建议您再次阅读一遍,因为我已经进行了一些更正,甚至添加了最后一个路径设置的步骤。如果有任何问题或困惑,请随时联系我,我会尽力帮助您。祝好运!

1
嗨!那听起来正是我想做的事情。如果你愿意分享你的代码,我会非常感激。如果不行,如果你能指点我正确的方向,我也很乐意自己学习,只是现在我甚至不知道该找什么... - Matthew Goulart
我明白了,先生。我现在正在通勤回家的路上,一到家就会为您提供一些代码供您使用。请稍等。 - GunnerFan420
1
非常感谢!!!我真的非常感激你所付出的努力。我将会仔细阅读你写的每一行代码,并尽可能多地学习它。这确实是一个很棒的答案,我无法感谢你的时间足够多!!! - Matthew Goulart
你懂的兄弟。我在使用SQL CE和EF时遇到了很大的困难,所以我想提供帮助。我不得不删除注释和许多错误处理,但方法名称应该有所帮助。我还编写了处理密码的代码,包括设置密码,如果需要,请告诉我。祝你好运,需要任何帮助就喊我。 - GunnerFan420

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接