איפה כדאי לשמור את המסד
-
- כאשר אני מריץ את התוכנית ומזין נתונים שונים בדטה-גרידים ושומר הכל במסד, סוגר פותח שוב הכל מופיע אבל אם אני עורך אי אלו שינויים ב MDF הרי שבפעם הבאה כאשר פותחים את התוכנה כל הנתונים מתאפסים, וזה קורה כי המסד שבתקיית הפלט הוחלף במסד מתקיית הפרוייקט, אז איך אפשר לשמור בכל זאת על כל הנתונים ? להחליף את הקונקשיין ? זה יסבך אתה כל.
תודה לכולם.
כשאתה בוחר את הקובץ בסייר הפיתרון, יש לך למטה הגדרה Copy To Output - תבחר שם Copy If Never - זה יגרום לIDE לא להעתיק אותו כל פעם אלא רק מתי שהוא לא נמצא בתיקיית הEXE.
@רחמים- נאמר שכבר הלקוח קיבל את התוכנה וכעת הוא רוצה להוסיף למסד עוד טבלה או או להוסיף לטבלה קיימת עוד עמודה וכדומה, הרי אני לא יכול לעשות את זה אצלי ולשלוח לו אלא אני צריך את המסד שלו שכבר מלא בנתונים ושם לערוך שינויים, אז איך אני אכניס את המסד שלו לפרוייקט השמור אצלי ואוסיף לו שם את ההוספות הנ''ל.
כמובן שאת כל זה אפשר לפתור בדרכי הטריקים אבל אני מחפש דרך ישרה ופשוטה, שה VS תוכנן מלכתחילה ללכת בה.
תודה לכולם.
אכן שאלה רצינית איך לטפל במסד נתונים, בפרט בתוכנת מדף זאת שאלה גדולה מאוד, אם רוצים לחסוך קוד, שמעתי פעם שיש פונקציה מוכנה שמשווה בין 2 מסדי נתונים ב sql server אבל לא יודע באמת אם להמר על זה.
במסדי נתונים לא יחסיים הבעיה הזאת לא מתחילה כמובן...
הפיתרון שלי כרגע, זה להחזיק טבלה מפלצתית שמכילה את כל המבנה של מסד הנתונים, זה אומר טבלה של טבלאות, טבלה של שדות, טבלה של מאפיינים (כל מאפיין שהוא לא ב default של המערכת, מקבל שורה שמכילה את שם המאפיין, ערך המאפיין, וקישור לשדה)
להגיד לך שזה ממלא את כל הציפיות שלי, לא ממש, ועל זה נאמר השם יעזור.
בהחלט יש את הפיתרון של ארכיטקט.
יש איזה פיתרון של VS, אבל זה משהו ביחד עם אשף הפריסה שלהם, - לא ממש התעסקתי עם זה.
הפיתרון שלי לעניין:
עשיתי בטבלת הSetting שדה שמחזיק את גירסת המסד האחרונה, במקביל, אני מחזיק קובץ (ובאקסס - טבלה מקומית ולא מקושרת) שמכילה עמודה של גירסה, וכן קוד SQL של שינוי מבני נתונים (נקרא גם DDL). - אתה יכול למצוא את הקוד של שינוי מבני הנתונים כשאתה עורך טבלה במנג'מנט, יש שם אפשרות לראות את הסקריפט SQL שמבצע את השינוי הזה.
אח"כ לכתוב פונקצייה שבודקת בDB בטבלה Setting מה גירסת הDB. במידה וזה קטן מהגירסה הנוכחית (אותה אתה יכול לשמור בהגדרות של התוכנה שלך, או במשתנה סטטי) אני מריץ שאילתת SQL בלופ, ואח"כ מעדכן בטבלה Setting את גירסת הDB החדשה.
זה עובד בהצלחה מדהימה כבר למעלה מ6 שנים, ואני לא חושש כלל להוסיף/ לשנות שדות - וגם להוסיף טבלאות.
לפני שאני ניגש לDB בפעם הראשונה אני מריץ את הפונצייה, ובא לציון גואל.....
בהצלחה!פורסם במקור בפורום CODE613 ב09/01/2014 14:43 (+02:00)
- כאשר אני מריץ את התוכנית ומזין נתונים שונים בדטה-גרידים ושומר הכל במסד, סוגר פותח שוב הכל מופיע אבל אם אני עורך אי אלו שינויים ב MDF הרי שבפעם הבאה כאשר פותחים את התוכנה כל הנתונים מתאפסים, וזה קורה כי המסד שבתקיית הפלט הוחלף במסד מתקיית הפרוייקט, אז איך אפשר לשמור בכל זאת על כל הנתונים ? להחליף את הקונקשיין ? זה יסבך אתה כל.
-
לגבי השאלה שניה אני הייתי עושה גירסאות של מסד נתונים. לפי מספר.
כלומר יש טבלה שיש שם אתה מספר של הגירסה. ובקוד יש מערך של פקודות לכל העלאת גירסה. כלומר כל שינוי במסד מתבטא בגירסה חדשה.
עכשיו אם נניח הגירסה במסד זה 10 ובתוכנה זה 20 אז הוא מריץ את כל הפקודות מ 11 עד 20 כדי לעדכן את המבנה של המסד.
עריכה: לא שמתי לב למה שכתב clickone קרדיט ל clickone הוא כתב את אותו רעיון.
פורסם במקור בפורום CODE613 ב09/01/2014 16:02 (+02:00)
-
אני ב-PHP משתמש בכלי האדיר הזה:
https://github.com/idler/MMPהוא פשוט יודע לייצר Schema של המסד ואז לעשות לו mirgrane במקומות האחרים על פי התאריך שלו.
זה כמין ניהול גירסאות בשביל Schema של המסד.צריך לחפש כזה כלי בשביל אקסס.
פורסם במקור בפורום CODE613 ב09/01/2014 16:44 (+02:00)
-
כשאתה בוחר את הקובץ בסייר הפיתרון, יש לך למטה הגדרה Copy To Output - תבחר שם Copy If Never - זה יגרום לIDE לא להעתיק אותו כל פעם אלא רק מתי שהוא לא נמצא בתיקיית הEXE.
ומה יהיה כאשר אני אוסיף טבלה למסד, הוא לא יעתיק? א''כ אז התוכנה תרוץ עם המסד הישן בלא הטבלה, ואם הוא כן יעתיק לאחר הוספת טבלה אז שוב אני אאבד את הנתונים שבטבלאות אחרות.
פורסם במקור בפורום CODE613 ב09/01/2014 22:48 (+02:00)
-
@ClickOne
כשאתה בוחר את הקובץ בסייר הפיתרון, יש לך למטה הגדרה Copy To Output - תבחר שם Copy If Never - זה יגרום לIDE לא להעתיק אותו כל פעם אלא רק מתי שהוא לא נמצא בתיקיית הEXE.ומה יהיה כאשר אני אוסיף טבלה למסד, הוא לא יעתיק? א''כ אז התוכנה תרוץ עם המסד הישן בלא הטבלה, ואם הוא כן יעתיק לאחר הוספת טבלה אז שוב אני אאבד את הנתונים שבטבלאות אחרות.
אם תשתמש במבנה שידרוג הDB שהצעתי (או אחרים ), אז את השינוי תעשה בDB שלא יועתק, וברגע שתפעיל את הEXE, הוא יזהה שגירסת הDB עם הנתונים האמיתיים שלך לא מעודכנת, וישדרג לך אוטו' את הDB.
מנסיון, עובד!
אם תרצה שאני יעלה דוגמה, אעשה זאת בשמחה!פורסם במקור בפורום CODE613 ב09/01/2014 22:54 (+02:00)
-
הנה הדוגמא... (לקח קצת זמן להגיע לזה, אבל זה מגיע בסוף.)
' קבוע השומר את גירסת המסד האחרונה Const CurrentVer As Integer = 3 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' שידרוג הDB UpDb() 'TODO: This line of code loads data into the 'DBDataSet.Demo1' table. You can move, or remove it, as needed. Me.Demo1TableAdapter.Fill(Me.DBDataSet.Demo1) End Sub Sub UpDb() ' הצהרה על קונקשיין Dim cnn As New SqlClient.SqlConnection ' משיכת מחרוזת החיבור מהגדרות האפליקציה cnn.ConnectionString = My.Settings.DBConnectionString ' פתיחת מחרוזת החיבור cnn.Open() ' בדיקה מהגירסת הדאטאבייס האחרונה Dim verCmd As New Data.SqlClient.SqlCommand("select DbVer From Setting", cnn) Dim dr As SqlDataReader = verCmd.ExecuteReader() dr.Read() Dim ver As Integer = dr.Item(0) ' סגירת הקורא. (לפעמים הוא עושה בעיות לשדרג כשזה פתוח) לכן אני סוגר אותו dr.Close() Try ' פתיחת קובץ טקסט מצורף והמרה לשורות במערך Dim DbUp As Array = Split(My.Computer.FileSystem.ReadAllText(CurDir() & "\DbUp.txt"), vbNewLine) Dim Row As Array For Each Line As String In DbUp 'המרת כל שורה למערך המפריד את גירסת המסד והקוד בשביל השידרוג Row = Split(Line, "|") ' בדיקה אם הגירסה יותר קטנה מהגירסה הנוכחית If Row(0) > ver Then UpDbSql(Row(1), cnn) Next 'עידכון הגירסה הנוכחית במסד הלקוח verCmd.CommandText = "UPDATE Setting SET DbVer = " & CurrentVer verCmd.ExecuteNonQuery() Catch ex As Exception MsgBox(ex.Message) End Try End Sub Sub UpDbSql(cmdSql As String, cnn As SqlClient.SqlConnection) Try ' הרצת הפקודה לשידרוג Dim cmd As New Data.SqlClient.SqlCommand(cmdSql, cnn) cmd.ExecuteNonQuery() Catch ex As Exception MsgBox(ex.Message) End Try End Sub
לצערי א"א להעלות לפורום קבצים מעל 256 KB ולכן זה לא עולה.
אז לחצו כאן כדי להוריד את זה מדרופבוקסמשתמשי אקסס:
-
אני ממליץ לעשות טבלה מקומית ולא לשים את הנתונים בקובץ חיצוני.
-
קוד הSQL DLL (של ההגדרת נתונים) מעט שונה.
במקום:CREATE TABLE [dbo].[Table3] ([Id] INT NOT NULL PRIMARY KEY IDENTITY, [LastName] NVARCHAR(50) NULL, [City] INT NULL)
צריך להיות:CREATE TABLE [Table3] ([Id] COUNTER PRIMARY KEY , [LastName] TEXT(50), [City] INT)
ובמקום:ALTER TABLE [dbo].[t1] ADD [f1] INT NULL
תשתמשו ב:ALTER TABLE [t1] ADD COLUMN [f1] INT
זה הכיוון, ואידך זיל גמור.
פורסם במקור בפורום CODE613 ב13/01/2014 01:12 (+02:00)
-
-
זה נראה ממש מצויין!
יישר כח גדול!מאיפה אני לוקח את נוסח הסקיפט שיוצר את כל הטבלאות והשאילתות במסד?
ב VS 2013 ראיתי שיש T-SQL ושם יש את הסקריפט של כל טבלה, אבל ב VS 2010 איפה זה נמצא?
כמו כן מי שמשתמש באקסס איפה נמצא הסקריפט?פורסם במקור בפורום CODE613 ב13/01/2014 08:47 (+02:00)
-
זה נראה ממש מצויין!
יישר כח גדול!מאיפה אני לוקח את נוסח הסקיפט שיוצר את כל הטבלאות והשאילתות במסד?
ב VS 2013 ראיתי שיש T-SQL ושם יש את הסקריפט של כל טבלה, אבל ב VS 2010 איפה זה נמצא?
כמו כן מי שמשתמש באקסס איפה נמצא הסקריפט?אני משתמש בVS2012 ושם יש באמת גם עידכון עפ"י השלבים הבאים:
שלב 1:
ואח"כ שלב 2:
אח"כ ייפתח חלון עם קוד SQL כזה:/* Deployment script for C:\USERS\CLICKONE\DOCUMENTS\VISUAL STUDIO 2012\PROJECTS\WPFSYNAGOGUE\WPFSYNAGOGUE\DB.MDF This code was generated by a tool. Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. */ GO SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON; SET NUMERIC_ROUNDABORT OFF; GO :setvar DatabaseName "C:\USERS\CLICKONE\DOCUMENTS\VISUAL STUDIO 2012\PROJECTS\WPFSYNAGOGUE\WPFSYNAGOGUE\DB.MDF" :setvar DefaultFilePrefix "C_\USERS\CLICKONE\DOCUMENTS\VISUAL STUDIO 2012\PROJECTS\WPFSYNAGOGUE\WPFSYNAGOGUE\DB.MDF_" :setvar DefaultDataPath "C:\Users\ClickOne\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\v11.0\ " :setvar DefaultLogPath "C:\Users\ClickOne\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\v11.0\ " GO : on error exit GO /* Detect SQLCMD mode and disable script execution if SQLCMD mode is not supported. To re-enable the script after enabling SQLCMD mode, execute the following: SET NOEXEC OFF; */ :setvar __IsSqlCmdEnabled "True" GO IF N'$(__IsSqlCmdEnabled)' NOT LIKE N'True' BEGIN PRINT N'SQLCMD mode must be enabled to successfully execute this script.'; SET NOEXEC ON; END GO USE [$(DatabaseName)]; GO IF (SELECT OBJECT_ID('tempdb..#tmpErrors')) IS NOT NULL DROP TABLE #tmpErrors GO CREATE TABLE #tmpErrors (Error int) GO SET XACT_ABORT ON GO SET TRANSACTION ISOLATION LEVEL READ COMMITTED GO BEGIN TRANSACTION GO PRINT N'Altering [dbo].[TblDonation]...'; GO ALTER TABLE [dbo].[TblDonation] ADD [cNow] DATETIME NULL; GO IF @@ERROR <> 0 AND @@TRANCOUNT > 0 BEGIN ROLLBACK; END IF @@TRANCOUNT = 0 BEGIN INSERT INTO #tmpErrors (Error) VALUES (1); BEGIN TRANSACTION; END GO IF EXISTS (SELECT * FROM #tmpErrors) ROLLBACK TRANSACTION GO IF @@TRANCOUNT>0 BEGIN PRINT N'The transacted portion of the database update succeeded.' COMMIT TRANSACTION END ELSE PRINT N'The transacted portion of the database update failed.' GO DROP TABLE #tmpErrors GO PRINT N'Update complete.' GO
שם תחפש את הקוד שמשנה את הטבלה. (בד"כ בשינוי מתחיל בALTER ובטבלה חדשה מתחיל בCREATE).
לגבי אקסס לא ידוע לי מקום מסויים שבו נמצא הקוד, אם כי הקוד מאד דומה, בשינוי קל (וכמו שכתבתי בהודעה המקורית). - אם תהיה דרישה אני ישתדל להעלות קוד שלוקח טבלה והופך אותה לקוד SQL DDL באקסס.
פורסם במקור בפורום CODE613 ב14/01/2014 21:41 (+02:00)
-
למי ששם לב בשורה 22 יש את הקוד הבא:
:on error exit
:on error exit
נהפך ל:
<img src="./images/smilies/icon_e_surprised.gif" alt=":o" title="מופתע">n error exit
מצחיק שהוא מפרש את נקודותיים O לסמיילי מופתע.
פשוט לא הבנתי מתי זה נדחף לקוד. לתשומת לב מנהלי האתר. (או המפתחים בPHP שמסתובבים כאן) - כשעושים הדגשות וצבעים בקוד זה לא נתפס, אז אם אפשר לפחות שלא יהרוס לנו את הקוד......פורסם במקור בפורום CODE613 ב14/01/2014 21:48 (+02:00)
-
בסוף הלכתי לפי הכיון שלך,
אבל את הסקריפט אני לוקח ע''י הפאבליש המובנה של VS,
כלומר כאשר לוחצים עם הימני של העכבר על המסד בחלון סרבר אקספלורר, מקבלים אפשרות של פאבליש ואז הוא מיצר קובץ *.SQL אם מריצים את כל הפקודות בקובץ זה בדומה לקוד שהבאת לעיל זה בונה את כל המסד מהתחלה עד הסוף, ולא צריך להחזיק ראש מה התווסף בכל גירסה.
אם יש צורך להוסיף טבלאות ו/או עמודות פשוט מיצאים בפאבליש שולחים ללקוח רק את קובץ .SQL ובעליית התוכנה היא בודקת אם יש קובץ SQL היא מעדכנת לפיו ואם לא עולה רגיל. הלקוח יקח את הקובץ ישים בתקיית התוכנה יפעיל פעם אחת ואם נרצה אפשר למחוק אותו משם.פורסם במקור בפורום CODE613 ב15/01/2014 00:14 (+02:00)
-
הנה מסד עם שתי טבלאות בלא תוכן ויש קשרי גומלין בינהם:
/****** Object: ForeignKey [FK_contacts_catgores] Script Date: 01/15/2014 00:40:30 ******/ IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_contacts_catgores]') AND parent_object_id = OBJECT_ID(N'[dbo].[contacts]')) ALTER TABLE [dbo].[contacts] DROP CONSTRAINT [FK_contacts_catgores] GO /****** Object: Table [dbo].[contacts] Script Date: 01/15/2014 00:40:30 ******/ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[contacts]') AND type in (N'U')) DROP TABLE [dbo].[contacts] GO /****** Object: Table [dbo].[catgores] Script Date: 01/15/2014 00:40:30 ******/ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[catgores]') AND type in (N'U')) DROP TABLE [dbo].[catgores] GO /****** Object: Table [dbo].[catgores] Script Date: 01/15/2014 00:40:30 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[catgores]') AND type in (N'U')) BEGIN CREATE TABLE [dbo].[catgores]( [ID] [int] IDENTITY(1,1) NOT NULL, [catrory] [nchar](10) COLLATE Hebrew_CI_AS NULL, CONSTRAINT [PK_catgores] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) END GO /****** Object: Table [dbo].[contacts] Script Date: 01/15/2014 00:40:30 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[contacts]') AND type in (N'U')) BEGIN CREATE TABLE [dbo].[contacts]( [ID] [int] IDENTITY(1,1) NOT NULL, [name] [nchar](10) COLLATE Hebrew_CI_AS NULL, [Lname] [nchar](10) COLLATE Hebrew_CI_AS NULL, [catgory] [int] NULL, CONSTRAINT [PK_contacts] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ) END GO /****** Object: ForeignKey [FK_contacts_catgores] Script Date: 01/15/2014 00:40:30 ******/ IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_contacts_catgores]') AND parent_object_id = OBJECT_ID(N'[dbo].[contacts]')) ALTER TABLE [dbo].[contacts] WITH CHECK ADD CONSTRAINT [FK_contacts_catgores] FOREIGN KEY([catgory]) REFERENCES [dbo].[catgores] ([ID]) GO IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_contacts_catgores]') AND parent_object_id = OBJECT_ID(N'[dbo].[contacts]')) ALTER TABLE [dbo].[contacts] CHECK CONSTRAINT [FK_contacts_catgores] GO
פורסם במקור בפורום CODE613 ב15/01/2014 00:42 (+02:00)
-
בדקתי ובאמת הנתונים נמחקים, מעיון בקובץ ה SQL עולה שקודם כל הוא עושה DROP לכל הטבלאות והקשרי גומלין ורק אחר כך יוצר טבלה אחר טבלה בתנאי שהיא לא קיימת כבר, כך שגם אם נדלג על פקודות ה DROP לא יתעדכנו הטבלאות הקיימות.
באפשריות של הפאבליש יש הגדרה שלא יעשה DROP לכל האובייקטים הישנים כך שאפשר מלכתחילה ליצור קובץ סקריפט ללא DROP אבל עדיין כל הפקודות בסקריפט הם של יצירת טבלה חדשה אם היא לא קיימת, אבל אם היא קיימת הוא לא יגע בה אף שחסר לה עמודות.
יש דרך להמיר את פקודות ה CREATE TABLE ל ALTER TABLE ?פורסם במקור בפורום CODE613 ב17/01/2014 00:36 (+02:00)
-
תחליף את CREATE
CREATE TABLE [dbo].[catgores]( [ID] [int] IDENTITY(1,1) NOT NULL, [catrory] [nchar](10) COLLATE Hebrew_CI_AS NULL, CONSTRAINT [PK_catgores] PRIMARY KEY CLUSTERED
ב ALTER,
תמחק את הסוגריים ותוסיף ADD, ואל תשכח להוציא את כל השדות שכבר קיימים....
בדוגמא להלן אני מניח שהיה רק שדה ID ולכן אני מסיר אותו ומשאיר את השארALTER TABLE [dbo].[catgores] ADD [catrory] [nchar](10) COLLATE Hebrew_CI_AS NULL
פורסם במקור בפורום CODE613 ב19/01/2014 00:38 (+02:00)