2010-07-06 82 views
3

到目前为止,我的公司已经厌恶数据库,并坚持将所有数据存储在逗号分隔文件中。我遇到了一个独特的客户应用程序 - 我相信 - 会从使用关系数据库中受益。该应用程序要求存储有关制造过程的'概要'数据和有关多个子过程的'详细'数据。子流程需要链接到流程摘要。在代码中创建不存在的数据库表

我的问题:在写入表格之前检查表格的存在并在表格不存在的情况下创建它是否正常/适当?这可能会导致更大的问题,现在我输入这个;如果数据库不存在,我应该创建数据库和它需要的任何表吗?

+2

'我的公司已经厌恶数据库,并坚持将所有数据存储在逗号分隔文件'OMG,恐怖。 – Pete 2010-07-06 10:34:53

+0

在某些情况下,我认为这是一个恐怖。我们具有轻松快速读写平面文件的所有优点,但无法处理关系数据,因为从来没有人打算开发它。 – Ryan 2010-07-06 10:53:31

回答

3

随着SQLite,自己创建表是一个好方法。您不需要为您的客户提供比以前更复杂的安装说明,并且如果数据库完全在您的应用程序内部,那么他们可能甚至不关心它的格式,只要您的软件是可靠和快速的。例如,Firefox现在使用SQLite作为其内部存储,并且它们从不打扰用户创建数据库。用户喜欢这种方式。 :)

但我不会过多地关注在引用表之前立即创建数据库:相反,我会将创建逻辑放在应用程序启动或安装时(以较合适的为准)。现在应用程序中创建的CSV文件在哪里?他们是否重新创建,每次被引用?或者它们是否在初始化或安装例程中创建?

+0

CSV文件分散在嵌套的目录结构中,并在应用程序启动时创建。在这个应用程序中,启动时的创建非常有意义。 – Ryan 2010-07-06 10:56:29

1

SubSonic SimpleRepository通常很好地处理这种情况(除了外键关系)。

通常我会倾向于不通过代码创建和维护数据库和/或表,因为这很容易在你的脸上炸毁。

1

对于这种类型的上下文,Sqlite具有“create table if not exist”语法。 (检查http://www.sqlite.org/lang_createtable.html)大多数库还可以选择在连接上创建新的sqlite数据库文件(如果它尚不存在)。

2

通常我会说,表的不存在意味着某个地方存在问题。动态创建的表通常是出错的标志,如果它们是标准表(例如tblUsers),那么它们应始终存在并已设置为设置过程的一部分。

我能想到的那种检查存在的时代是有道理的,一旦你在代码开发中有一定的距离,并且升级数据库来添加额外的表,但是希望你的代码使用这个新设计和旧的。在这种情况下,在尝试使用它们之前检查表的存在是有道理的。

一般来说,虽然你应该知道你的数据库里有哪些表,所以不需要检查它们的存在。而我完全失去了为什么你会试图访问不存在的数据库......你是否想过一种懒惰的设置过程,可以在新的客户端(或类似的)上快速添加新的客户端(或类似的)数据库创建?如果是这样的话,我会有一个过程来创建和设置这些新的数据库。

3

不,在代码中创建表是不正常的。如果您需要关系数据库,则需要在使用前进行设计。关系数据库不会被忽略。

如果你从来没有做过这个已经,这里是介绍对象...... http://www.databasedev.co.uk/design_basics.html

(很抱歉,如果你知道这一切,我的意思不是光顾。)

+0

使用前设计数据库是正常的。但对于使用基于文件的数据库的桌面应用程序,通过代码创建数据库可能是适当的。这在许多应用程序共享一个服务器数据库的企业环境中是不同的。 – MarkJ 2010-07-06 12:59:18

+0

你的意思是安装它吗?我认为Ryan在应用程序运行时意味着;这真的很正常吗?我的意思是,除了数据库定义工具。 或者我在这里得到了棒的错误结局? – 2010-07-06 13:15:47

+1

这是不正确的。在某些情况下,商业应用程序创建表甚至整个数据库。针对各种客户提供的数据库服务器运行的应用程序通常创建整个数据库作为安装过程的一部分。在新版本中发布的应用程序通常会在每个版本中升级其数据库(包括添加表)。 – 2010-07-06 15:15:03

0

关系数据库允许轻松共享数据。

您可以在不需要共享数据时使用文件。

对于存储文件信息,DataSet序列化是一个很好的选择。您维护像关系数据库一样结构化的数据。

XML序列化是缓慢的,但你可以使用的BinaryFormatter有:

RemotingFormat = SerializationFormat.Binary 

此选项使快速和紧凑的二进制序列化。

Code-Project包含一个“快速序列化”文章。但这不是标准。

1

在编写应用程序之前,您应该知道数据的结构。

尽可能将数据和应用程序分开。

使用数据访问层还意味着如果您已经有Windows应用程序(例如),然后想要创建Web前端,则可以轻松地重新使用DAL。

如果数据访问被嵌入到应用程序中,那么重用该代码将变得更加困难。

+0

......此外,如果数据库模式创建被嵌入到应用程序中......不寒而栗! – onedaywhen 2010-07-07 12:45:58

0

答案取决于项目的性质。

如果这是一个带有单个实例的内部系统,那么在您更新软件时,节省一些开发时间并手动更新数据库是合理的。在这种情况下,你不用担心你的软件会添加表格。

如果您将此软件提供给客户或组织内的远程站点,并且安装和升级发生在“现场”,那么每个新版本的软件都应该自行升级数据库是合理的。您不一定希望在每个SQL命令之前执行此检查,而不一定要在每次运行该软件时进行检查。您可以在数据库某处存储“数据结构版本号”,并在启动时检查该数字,如果该数字低于当前版本,则仅应用结构更新。

0

许多RDBMS支持DDL SQL语句。 ADOX可以与一些数据库一起使用来完成创建新表等操作。我认为这根本不是特别奇特的,特别是当一个程序使用某种“嵌入式”基于文件的数据库作为内部数据存储或者甚至作为输出格式时。

根据需要创建索引,约束,关系等没有问题。例如:

Private Const WG_CONNSTRING As String = _ 
     "Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Engine Type=5;" _ 
    & "Jet OLEDB:Create System Database=True;" _ 
    & "Data Source='$MDB$.mdw'" 
Private Const DB_CONNSTRING As String = _ 
     "Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Engine Type=5;" _ 
    & "Jet OLEDB:System Database='$MDB$.mdw';" _ 
    & "Data Source='$MDB$.mdb'" 

'Exits with new MDB created, populated from initial data 
'in text files, and cnDB left open. 

Dim catDB As Object 'Don't early-bind ADOX objects. 

Set catDB = CreateObject("ADOX.Catalog") 
catDB.Create Replace$(WG_CONNSTRING, "$MDB$", MDB_NAME) 
catDB.Create Replace$(DB_CONNSTRING, "$MDB$", MDB_NAME) 

Set cnDB = catDB.ActiveConnection 
With cnDB 
    .Execute "CREATE TABLE Fruits (" _ 
      & "FruitID IDENTITY NOT NULL CONSTRAINT PK_FruitID PRIMARY KEY," _ 
      & "Fruit TEXT(50) WITH COMPRESSION NOT NULL UNIQUE" _ 
      & ")", _ 
      , adCmdText 
    .Execute "CREATE TABLE Pies (" _ 
      & "PieID IDENTITY NOT NULL CONSTRAINT PK_PieID PRIMARY KEY," _ 
      & "Pie TEXT(50) WITH COMPRESSION NOT NULL," _ 
      & "FruitID INTEGER NOT NULL CONSTRAINT FK_FruitID " _ 
      & "REFERENCES Fruits (FruitID)" _ 
      & ")", _ 
      , adCmdText 
    .Execute "CREATE VIEW PiesView (ID, Pie, Fruit) AS " _ 
      & "SELECT PieID AS ID, Pie, Fruit " _ 
      & "FROM Pies LEFT OUTER JOIN Fruits " _ 
      & "ON Pies.FruitID = Fruits.FruitID", _ 
      , adCmdText 
    .Execute "CREATE PROC InsertPie(NewPie TEXT(50), FruitName TEXT(50)) AS " _ 
      & "INSERT INTO Pies (Pie, FruitId) " _ 
      & "SELECT NewPie, Fruits.FruitId FROM Fruits " _ 
      & "WHERE Fruit = FruitName", _ 
      , adCmdText 
End With