Can I store extra data in a Guid - c#

Can we implement a custom GUID in C# with string values and again fetch the custom string data from GUID parsing? It may not sound practical, but just to know the process and its de-merits.
Suppose we have a database table CUSTOMER with Cust_Data column as uniqueidentifier datatype. From C#, we created method to generate GUID and put in DB table. for example
public Guid GetCustomGuid(Guid guidValue , string customerData)
{
// Method implementation
// Create New GUID as ==> guidValue + customerData;
return //Guid created
}
Once the GUID is generated , we again parse the GUID from DB and fetch the customer data.
public string GetCustomData(Guid GuidFromDB)
{
// Method implementation for parsing the guid.
// fetch the custom data from GuidFromDB.
// Every GUID received is always unique with respect to customer data.
return //CustomerData;
}
I didn't know whether, I put the question exact context, please edit it, if required.

A column of type uniqueidentifier can store 16 bytes. This is in general not enough to leave room for extra data and is certainly not in anyway suitable to ensure that the column is still unique once you start dropping bytes from the Guid to make room. There's no GU in guid anymore when you do that, it is no longer guaranteed to be globally unique. The random index collisions you get are of course very unpleasant.
There's no point, just add an extra column to the table. Maybe you want a clustered index, it isn't clear from the question.

One of this biggest reasons NOT to do this is because if the GUID is relative to some customer data, and you change that data, you change the Guid. This would break referential integrity in the database. Row Identifers are not support to, in and of themselves, contain data about row, only how the row is related to other rows.

Related

Generating IDs for Items in an Inventory System

So I am making an inventory system as a school project and I want to generate a Unique IDs for the items so that it will be the identifier for that certain Item.
Is it possible to generate an ID which is based on certain fields such as the item name, the price, the expiration.
Is there some existing library I can use for this?
EDIT: It is okay for my system to have duplicate ids because it will mean that the item already exists in the system and does not need to be added again.
Is it possible to generate an ID which is based on certain fields such as the item name, the price, the expiration.
Yes: a hash.
For example:
// It's very important to use `InvariantCulture ` and "o" to ensure consistent formatting on all computers
String infoText = item.Name + item.Price.ToString( "C2", CultureInfo.InvariantCulture ) + item.Expiration.ToString("o");
Byte[] infoBytes = Encoding.UTF8.GetBytes( infoText );
using( SHA256 sha = new SHA256Cng() )
{
Byte[] hash = sha.ComputeHash( infoBytes );
String hashText = Convert.ToBase64String( hash );
Console.WriteLine( "{0} = {1}", infoText, hashText )
}
A hash (also known as a "digest") will always be the same for the same input, and will be different for different input.
So if you have an SKU containing $10 worth of apples that expires on 2019-10-09, and you feed that in to the code above, then it will generate a unique code you can use without needing to store the mapping between that SKU and that unique code (also known as "content-based addressing").
...so if you come across another $10 worth of apples that also expire on 2019-10-09, then it will have the same unique code, even though it's a different object, and you didn't need to memorize that unique code you generated earlier.
But if you come across $10 worth of pears that expires on 2019-10-09, or $20 worth of apples that also expires on the same day, the'll have a different code.
You could create the ID by concatenating all of the information together as a big string or even hashing that string.
However this can still give you duplicates if all of that information is that same several times. There doesn't seem to be any need on using the existing information to generate the ID. If you are basing it on existing data then there will always be a chance of duplicates. Unless there is some sort of constraint on one of the fields requiring that to be unique. But if that's unique then you could just use that as an ID in the first place.
If you are storing this data in a database I would suggest creating an ID field and make that the primary key and give it an identity. This will automatically increment the ID so it will always be unique.
You could also just generate a GUID by using Guid.NewGuid() and use that as the ID.
Is it possible to generate an ID which is based on certain fields such as the item name, the price, the expiration.
Joining these three strings or even hashing them still have the chance of being duplicate.
Simple question needs simple solution, why not using a running number? Since you have an inventory system, for the first item in your inventory system that should be ID#1 (or you can start with any numbers you like).
But if you insist to use certain fields information i would suggest that adding all below information together:
combination of fields information
timestamp
user id(person who perform the insert)
maybe your favorite colors
hashing all information above

Redirect queries from one entity to another using c# / entity framework

This is a bit of a puzzle I'm trying to figure out.
I am working on a system where we have a number of company records saved in the database. Some of these records are duplicates and are no longer wanted/required.
However, several external systems are still mapping to these invalid records. If we were to delete them entirely it would cause errors to the systems still wanting to get the detail of that company.
The ideal workflow I would like would be;
The external system looks up Company ID X.
The current system has a table which has a record of all the remapped records, so when the request comes in, the table specifies to redirect Company ID X to Company ID Y.
There are a number of endpoints that could be altered one-by-one to do this - but it would be time-consuming, resulting in lots of repetition too.
My question is, using Entity Framework and .Net - is there a smart way of achieving this workflow?
My initial thoughts were to do something with the constructor for the company object, which repopulates the object from EF if a 'redirect' exists, but I don't know if this will play nice with navigation properties.
Would anyone have an idea?
Thanks very much.
You can create a column with foreign key for the same table to express the single unique valid company.
For example, you can add DuplicateOf column:
ALTER TABLE [Company]
ADD COLUMN [DuplicateOf] bigint NULL,
FOREIGN KEY [DuplicateOf] REFERENCES [Company] ([Id]);
and express this relation in your code:
public class Company
{
// ...
public Company DuplicateOf { get; set; }
// May be useful, hides check for duplicate logic:
public bool IsDuplicate => DuplicateOf != null;
// May be useful as well,
// returns the non-duplicate uniue company, not a duplicate, either linked or current:
public Company EffectiveCompany => DuplicateOf ?? this;
}
You will have to address EffectiveCompany when you want to work with non-duplicate and maintain this column to always point to the correct record. It will also result into additional query, if eager-loaded.
Another idea is to have a stored procedure GetCompany(bigint id) which will return the effective record - if DuplicateOf exists, or record itself otherwise. It will be good for your external systems and will let you hide all this stuff behind abstraction layer of stored procedure. If you decide to change it in future, then you can easily update it without breaking external systems.
However, for you it isn't always convenient to work with stored procedures with EF.
These are just ideas and not the best solutions, anyway.
In my opinion, the best solution would be to get rid of duplicates, update data everywhere and forget forever about this mess of duplicated data.

Get Identity Attribute value before inserting in Database

I have a table and it has one of the attribute set as identity. I want to get the value of the identity attribute that would be generated after I enter a value to the database.
I have EmpTable made of EmpID and EmpName. EmpID is set as Identity. I want to fetch the EmpID value before inserting a new row to the database.
I would advise against trying to do this with a table that is set up to use an integer column as the primary key. You will run into concurrency problems if you simply fetch the previous ID and increment it. Instead you should use a GUID (uniqueidentifier in SQL) as your primary key.
This will allow you to generate a new GUID in your code that can safely be saved to the database at a later stage.
http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
http://msdn.microsoft.com/en-us/library/ms187942.aspx
Sure the server knows where the auto-increment count is in its sequence, but there is almost nothing useful you can do with that information. Imagine you go to the Post Office and they hand out numbered tickets so they can serve customers in order. Of course you could ask them what the next number they'll give out is, but since anyone can walk in at any time you don't know you'll get that number. If you don't know that you'll get it, you can't do anything with it - e.g. writing it as a reference number on a form would be a mistake.
Depending on what you're trying to do, your two main options are:
Use a client-generated guid as your identifier. This kind of messes up the order so the analogy isn't great, but imagine if each customer who walked in could generate a random number that they are sure would never have been used before. They could use that to fill out forms before taking a number.
Take a number, but do it in a transaction with the other operations. A customer can take a number and use it to fill out some paperwork. If they realize they left their money at home, they just throw everything away and you never call their number.
Why do you think you need this information? Can you use either of these strategies instead?

How do I store a List<> as a field in a database? - C# (SQL Server Compact Edition)

I have an object whose fields I would like to store in a database. I will be using SQL Server Compact Edition (with Visual C# Express 2010). For the record, I'm fairly new to programming with databases (and databases in general). This program will be used every day to read emails, process the orders inside them, store them, and access them when necessary to help with completing the orders. The list of orders is going to become much to large to store in a List, write to a file, create the List from a file, etc. The problem is that each order contains a list of the items purchased. I am aware that I can serialize the list in binary or XML, and use that data as the field. However, this prevents me from searching/selecting based on that list. For instance, if I wanted to find an order based on what items are in it, or see how many times a particular item has been purchased. Since the list will be of arbitrary size, I can't just create a bunch of fields and fill only the ones I need (which in my opinion, is a bad idea anyway).
While writing this I realized a mistake. If I serialize the list again, I could compare the serialized data to find the same list again (though, this assumes that the same data is serialized the same way each time). However, I'm still prevented from finding any particular item.
So, is there any way to store the list of items, in a fixed number of fields (preferably 1) and still be able to search its contents with a query (I will most likely be using LINQ)?
Edit:
To address what I've gotten so far: first, thanks! I'm starting to piece together what I have to do, but I'm not quite there. The consensus seems to be to have a table for each set of items. Does that mean I'd be creating thousands of tables each month?
After re-reading my question I realize I have to be more clear. As the order comes in, I parse the data and store it in an Order object, which consists of the customer's information, and the list of items. Here is a simplified version of what I'm trying to store:
class Order{
private DateTime date;
private String orderNumber;
private String buyerName;
private List<Item> items;
private String address;
}
class Item{
private String itemCode;
private String description;
private int quantity;
}
So would I have to create a new table for each List I create, or am I missing something?
Update:
This may be a helpful reference for One-to-many relationships if you are new to the subject (especially check out the second and most upvoted answer): Create a one to many relationship using SQL Server
You'll want to create a new table in the database for your line items then create a foreign key relationship to the order table. It will be a one to many relationship. Some thing like the following - obviously you'll need to create a FK relationship, but you get the gist.
Existing
CREATE TABLE Order (
OrderID INT,
PONumber VARCHAR,
ItemsList VARCHAR
)
New
CREATE TABLE Order (
OrderID INT,
PONumber VARCHAR
)
CREATE TABLE LineItem(
LineItemID INT,
Description VARCHAR,
Quantity INT,
SequenceNumber INT,
OrderID INT -- <--- Important one here
)
Note that if you want to create just a simple lookup, the relationship would go the other way.
Instead of storing the list as a field, you can create a separate table that hold it's items. And records in this ListTable will have a field pointing to record ID in your original table. That way you can write various queries afterwards.
This can be solved in several ways, but if you want to be able to query the data directly, you should redesign your database with a seperate table where you store your list data with a reference ID. After all, databases are all about data lists.

C#: Is it possible to store a Decimal Array in an SQL database?

I'm working on an application for a lab project and I'm making it in C#. It's supposed to import results from a text file that is exported from the application we use to run the tests and so far, I've hit a road block.
I've gotten the program to save around 250 decimal values as a single-dimension array but then I'm trying to get the array itself to be able to saved in an SQL database so that I can later retrieve the array and use the decimal values to construct a plot of the points.
I need the entire array to be imported into the database as one single value though because the lab project has several specimens each with their own set of 250 or so Decimal points (which will be stored as arrays, too)
Thanks for your help.
EDIT: Thanks for the quick replies, guys but the problem is that its not just results from a specimen with only 1 test ran. Each specimen itself has the same test performed on them with different decibel levels over 15 times. Each test has its own sets of 250 results and we have many specimens.
Also, the specimens already have a unique ID assigned to them and it'd be stored as a String not an Int. What I'm planning on doing is having a separate table in the DB for each specimen and have each row include info on the decibel level of the test and store the array serialized...
I think this would work because we will NOT need to access individual points in the data straight from the database; I'm just using the database to store the data out of memory since there's so much of it. I'm going to query the database for the array and other info and then use zedgraph to plot the points in the array and compare multiple specimens simultaneously.
Short answer is absolutely not. These are two completely different data structures. There are work arounds like putting it in a blob or comma separating a text column. But, I really hate those. It doesn't allow you to do math at the SQL Server level.
IMO, the best option includes having more than one column in your table. Add an identifier so you know which array the data point belongs to.
For example:
AutoId Specimen Measurement
1 A 42
2 A 45.001
3 B 47.92
Then, to get your results:
select
measurement
from
mytable
where
specimen = 'A'
order by
autoid asc
Edit: You're planning on doing a separate 250 row table for each specimen? That's absolutely overkill. Just use one table, have the specimen identifier as a column (as shown), and index that column. SQL Server can handle millions upon millions of rows markedly well. Databases are really good at that. Why not play to their strengths instead of trying to recreate C# data structures?
I need the entire array to be imported
into the database as one single value
though because the lab project has
several specimens each with their own
set of 250 or so Decimal points (which
will be stored as arrays, too)
So you're trying to pound a nail, should you use an old shoe or a glass bottle?
The answer here isn't "serialize the array into XML and store it in a record". You really want to strive for correct database design, and in your case the simplest design is:
Specimens
---------
specimenID (pk int not null)
SpecimenData
------------
dataID (pk int not null
specimenID (fk int not null, points to Specimens table)
awesomeValue (decimal not null)
Querying for data is very straightforward:
SELECT * FROM SpecimenData where specimenID = #specimenID
As long as you don't to access the the individual values in your queries, you can serialize the array and store it as a blob in the database.
Presumably you could serialize the decimal array in C# to a byte array, and save that in a binary field on a table. Your table would have two fields: SpecimenID, DecimalArrayBytes
Alternately you could have a many to many type table and not store the array in one piece, having fields: SpecimenID, DecimalValue, and use SQL like
SELECT DecimalValue FROM Table WHERE SpecimenID = X
You can serialize the array and store it as a single chunk of xml/binary/json. Here is an example of serializing it as xml.
public static string Serialize<T>(T obj)
{
StringBuilder sb = new StringBuilder();
DataContractSerializer ser = new DataContractSerializer(typeof(T));
ser.WriteObject(XmlWriter.Create(sb), obj);
return sb.ToString();
}
You want two tables. One to store an index, the other to store the decimal values. Something like this:
create table arrayKey (
arrayId int identity(1,1) not null
)
create table arrayValue (
arrayID int not null,
sequence int identity(1,1) not null,
storedDecimal decimal(12,2) not null
)
Insert into arrayKey to get an ID to use. All of the decimal values would get stored into arrayValue using the ID and the decimal value to store. Insert them one at a time.
When you retrieve them, you can group them by arrayID so that they all come out together. If you need to retrieve them in the same order you stored them, sort by sequence.
Although any given example might be impractical, via programming you can engineer any shape of peg into any shape of hole.
You could serialize your data for storage in a varbinary, XML-ize it for storage into a SQL Server XML type, etc.
Pick a route to analyze and carefully consider. You can create custom CLR libraries for SQL as well so the virtual sky is the limit.

Categories