Set a permanent value of a variable without using a database - c#

I don't know how to describe it thoroughly in the title, but I need to set a permanent value of a variable/flag once a process has return true and maybe set some flag in the program itself the value rather than saving it to database. And once that variable/flag has already have that value then the program won't run the process again and just use the value. Is it possible? I'm using VB.Net. I can't use the database because database can be overridden and change values by using query. Thanks in advance!

You can simply use binary/XML serialization in a file to save the state of that variable through your program. Every time you restart your app you can access the value from that file to get its current state.
You can look at this example - http://www.centerspace.net/examples/nmath/csharp/core/binary-serialization-example.php
Basically, you will not save the value in the database but in a file. Anyways you need to persist the value somewhere.

Some ways below
You did not specify if you are afraid that your application or another one could change the value
How I would do it
My ideas below
1)You could use an xml file for example and zip a copy of it with a strong password. Every time you update the first xml you will update also the encrypted zipped xml.You can use a FileSystemWatcher and capture any file change, so if something/someone has changed the file you just get a new copy from the zip
2)You can store the value in the DB and add a trigger to prevent delete/update
for example
-- delete trigger
CREATE TRIGGER Function_Value_Deleted
ON [dbo].[FunctionsValueTb]
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (
SELECT [Flag] FROM deleted
)
BEGIN
ROLLBACK;
RAISERROR ('Record deletion is not allowed...', 16, 1);
END
END
*You can use also use THROW rather than RAISERROR
**Do the same for the insert and update actions
***You can also store the value into a log table or send an email

I found myself in a situation quite similar to yours a couple of days ago.
In the end, I decided to use the settings functionaly provided by .NET: it is easy to use and maintain, and so far it has given me good results.
Yo can see here what I am talking about:
Best practice to save application settings in a Windows Forms Application
That thread refers to C# but is easily applicable for VB.NET: I just had to follow the same steps in order to add the Settings file:
Right click on the project in Solution Explorer, choose Properties.
Select the Settings tab, click on the hyperlink if settings doesn't
exist. Use the Settings tab to create application settings. Visual
Studio creates the files Settings.settings and
Settings.Designer.settings that contain the singleton class Settings
inherited from ApplicationSettingsBase
And then, from my code, I use the settings like this:
Dim lastExecDate As Date = My.Settings.LastSuccessfulExecution
lastExecDate = lastExecDate.AddDays(1)
// Perform my next execution and do other stuff
My.Settings.LastSuccessfulExecution = lastExecDate
My.Settings.Save()
Next time you retrieve the parameter LastSuccessfulExecution, it will have the updated value.
One more remark, as stated in the post that I linked above:
Note that you need to set the scope property of your settings. If you
select Application scope then Settings.Default.< your property > will
be read-only
Finally, I see that you are using this to store the expiration date of a product, so you don't want the user messing around with it. According to this post, the actual values of the parameters are stored in an Application Data user folder. It is somehow obfuscated since it is not that easy to find and besides it contains a hash on its name... I don't know if that is well hidden enough for you.

If you want the value only to exist in memory when the application is running then you can use the main thread of the application and use:
int slotData = randomGenerator.Next(1, 200);
//to set the data
Thread.SetData(Thread.GetNamedDataSlot("SomeDataKey"), slotData);
//to get the data
int newSlotData = (int)Thread.GetData(Thread.GetNamedDataSlot("SomeDataKey"));
Or you can use the Windows Registry if your app only runs on Windows, if not then you would have to write the value/object to a file and read it from there.

Related

Saving Data On C# Wpf

How can I save my added buttons when closing the program ? Each time I hit an add button I'm creating a new title which type is button.And each title have it's own specific words.So I must save the words in buttons at the same time.
Find out what data needs to be stored. > Define a Model
Define how the Data will be stored > e.g. XML-Serialisation, JSON or whatever
Define where Data will be stored, e.g. Database, File
Define when the Configuration is read and saved
eg: read on startup, save on shutdown
Handle your Configuration Data to generate your buttons
Its all up to you. :)
An easy solution might be using XmlSerializer, which is documented here.

Multiple values for a key in App.config

I want to write a key and multiple values in app.config, so that depending on the value a method is run.
for example:
let the key be "syncMode" and values to be kept are "syncAll"/"syncYest"
If the value is set as syncAll, complete data sync should happen in the main program and if syncYest is set, then only yesterday's data should be sync.
How can i write this in App.config?
Based on your requirement this looks like a simple case of single name and single value.If you want "Complete data sync in the main program" set value of key syncMode = "syncAll".Otherwise if you want "yesterdays data to sync" use syncMode = "syncYest"
You can create a custom configuration section for this. There is already a SO Post related to this. Additionally, you can also read the official MSDN page.

Database changes do not persist after ObjectContext.SaveChanges() is called

I am trying to insert a record into a table using an Entity Framework. I made my database (mdf file), made a model from the database (edmx), and now I am trying to insert a record.
Users Brad = new Users
{
UserInitials="BCH",
UserName="Brad"
};
using (WeighProgramDatabaseEntities wDB = new WeighProgramDatabaseEntities())
{
wDB.Users.AddObject(Brad);
int res = wDB.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave);
List<Users> lwt = wDB.Users.ToList(); //call to look at the inserted data
}
When I follow this procedure it appears everything works fine. My wDB.Users.ToList(); returns one record which is the one I just inserted. However, if I run my code again, removing the insert stuff and just call the query (leaving just) List<Users> lwt = wDB.Users.ToList(); my query returns no records. What should I be doing differently to get my changes to persist? Why did my records "go away"?
WeighProgramDatabaseEntities inherits from ObjectContext.
This is my first attempt at using EF stuff so some of my verbiage might not be correct and I might not have included something important - let me know.
Edit:
I think my problem is that my Insert/Update/Delete functions are not mapped. But I'm not sure how to create a stored procedure for them to map to...
Edit2:
Ok, phew, I figured out the stored procedure mapping. and now that I have an INSERT mapped, and I call AddObject it will actually be inserted.
A little more complicated than I would have expected. For example if I right click on a table in my Database Explorer and select New Query it brings me to a great query designer window which let's me create Inserts, Selects, Updates... but there is no Save button! It's grey out. I need to write them from another route with does not let me generate Inserts/Deletes/Updates via a GUI. Which is ok I guess because they are not much text, but still a bit of a hassle.
I think that your ConnectionString points to the mdf in the Debug/Release folder of your solution, and that file is probably overwritten each time you build your application that's why you think your changes are not persisted. Try setting the ConnectionString to point to the mdf in the project folder (the one that is actually reference by the project).
You can also set the "Copy to output directory" file property to "Copy if newer" rather than "Copy always". If you update the schema of the database in your project then it becomes newer than the database file in the debug directory and it will be overwritten on compile.

SSIS Task for inconsistent column count import?

Problem.
I regularly receive a feed files from different suppliers. Although the column names are consistent the problem comes when some suppliers send text files with more or less columns in there feed file.
Furthermore the arrangement of these files are inconsistent.
Other than the Dynamic data flow task provided by Cozy Roc is there another way I could import these files. I am not a C# guru but i am driven torwards using a "Script Task" control flow or "Script Component" Data flow task.
Any suggestion, samples or direction will greatly be appreciated.
http://www.cozyroc.com/ssis/data-flow-task
Some forums
http://www.sqlservercentral.com/Forums/Topic525799-148-1.aspx#bm526400
http://www.bidn.com/forums/microsoft-business-intelligence/integration-services/26/dynamic-data-flow
Off the top of my head, I have a 50% solution for you.
The problem
SSIS really cares about meta data so variations in it tend to result in exceptions. DTS was far more forgiving in this sense. That strong need for consistent meta data makes use of the Flat File Source troublesome.
Query based solution
If the problem is the component, let's not use it. What I like about this approach is that conceptually, it's the same as querying a table-the order of columns does not matter nor does the presence of extra columns matter.
Variables
I created 3 variables, all of type string: CurrentFileName, InputFolder and Query.
InputFolder is hard wired to the source folder. In my example, it's C:\ssisdata\Kipreal
CurrentFileName is the name of a file. During design time, it was input5columns.csv but that will change at run time.
Query is an expression "SELECT col1, col2, col3, col4, col5 FROM " + #[User::CurrentFilename]
Connection manager
Set up a connection to the input file using the JET OLEDB driver. After creating it as described in the linked article, I renamed it to FileOLEDB and set an expression on the ConnectionManager of "Data Source=" + #[User::InputFolder] + ";Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=\"text;HDR=Yes;FMT=CSVDelimited;\";"
Control Flow
My Control Flow looks like a Data flow task nested in a Foreach file enumerator
Foreach File Enumerator
My Foreach File enumerator is configured to operate on files. I put an expression on the Directory for #[User::InputFolder] Notice that at this point, if the value of that folder needs to change, it'll correctly be updated in both the Connection Manager and the file enumerator. In "Retrieve file name", instead of the default "Fully Qualified", choose "Name and Extension"
In the Variable Mappings tab, assign the value to our #[User::CurrentFileName] variable
At this point, each iteration of the loop will change the value of the #[User::Query to reflect the current file name.
Data Flow
This is actually the easiest piece. Use an OLE DB source and wire it as indicated.
Use the FileOLEDB connection manager and change the Data Access mode to "SQL Command from variable." Use the #[User::Query] variable in there, click OK and you're ready to work.
Sample data
I created two sample files input5columns.csv and input7columns.csv All of the columns of 5 are in 7 but 7 has them in a different order (col2 is ordinal position 2 and 6). I negated all the values in 7 to make it readily apparent which file is being operated on.
col1,col3,col2,col5,col4
1,3,2,5,4
1111,3333,2222,5555,4444
11,33,22,55,44
111,333,222,555,444
and
col1,col3,col7,col5,col4,col6,col2
-1111,-3333,-7777,-5555,-4444,-6666,-2222
-111,-333,-777,-555,-444,-666,-222
-1,-3,-7,-5,-4,-6,-2
-11,-33,-77,-55,-44,-666,-222
Running the package results in these two screen shots
What's missing
I don't know of a way to tell the query based approach that it's OK if a column doesn't exist. If there's a unique key, I suppose you could define your query to have only the columns that must be there and then perform lookups against the file to try and obtain the columns that ought to be there and not fail the lookup if the column doesn't exist. Pretty kludgey though.
Our solution. We use parent child packages. In the parent pacakge we take the individual client files and transform them to our standard format files then call the child package to process the standard import using the file we created. This only works if the client is consistent in what they send though, if they try to change their format from what they agreed to send us, we return the file.

Best Practice - Handling multiple fields, user roles, and one stored procedure

I have multiple fields both asp:DropDownList's and asp:TextBox's. I also have a number of user roles that change the Visible property of certain controls so the user cannot edit them. All of this data is saved with a stored procedure call on PostBack. The problem is when I send in the parameters and the control was not on the page obviously there wasn't a value for it, so in the stored procedure I have the parameters initialized to null. However, then the previous value that was in the database that I didn't want changed is overwritten with null.
This seems to be a pretty common problem, but I didn't have a good way of explaining it. So my question is, how should I go about keeping some fields from being on the page but also keeping the values in the database all with one stored procedure?
Apply the same logic when chosing what data to update as the logic you're actually using when chosing what data (and its associated UI) to render.
I think the problem is you want to do the update of all fields in a single SQL update, regardless of their value.
I think you should do some sanity check of your input before your update, even if that implies doing individual updates for certain parameters.
Without an example, it is a little difficult to know your exact circumstances, but here is a fictitious statement that will hopefully give you some ideas. It is using t-sql (MS SQL Server) since you did not mention a specific version of SQL:
UPDATE SomeImaginaryTable
SET FakeMoneyColumn = COALESCE(#FakeMoneyValue, FakeMoneyColumn)
WHERE FakeRowID = #FakeRowID
This basically updates a column to the parameter value, unless the parameter is null, in which case it uses the columns existing value.
Generally to overcome this in my update function
I would load the current values for the user
Replacing any loaded values with the newly changed values from the form
Update in db.
This way I have all the current plus everything that has been changed will get changed.
This logic will also work for an add form because all the fields would be null then get replaced with a new value before being sent to the db. You would of course just have to check whether to do an insert or update.

Categories

Resources