Entity Framework and changing table schema/structure - sql

I was wondering if someone knows if the following is somehow possible using EF or some other ORM.
We have a number of tables in a database. Like this one "Person"
Id
Name
Phone
Email
This is the same for all databases and will not change, it's our base table so to speak :)
Now one database might have a table also called "Person", it's the same but with an extra column Phone.
Id
Name
Phone
Email
Phone
Is there a way to have the Phone column available in the entity like a Dictionary<string,object>? I am actually only looking for basic select queries to support this. So I won't need a separate model for all databases.
Or is it just not possible? :)
--
Christian

Linq To Sql or Linq To Entities are designed to work on static table schema, I'm afraid you'll have to use ADO.NET to get what you want, or go to another schema (FK from some other tables containing key values pairs for exemple)

Related

Good practices between SQL and elasticsearch

Imagine you have a SQL database like mysql or postgresql. You have two tables : user and car. One user can drive N cars, a car can be driven by N users, so you have a third "drive" table with two foreign key.
Now, you want that your table user goes on elasticsearch, because you want search users by name, email... etc... Maybe you also need to do some search on the car table.
I see three way to achieve this, I d'like to know what is the best way :
1) Abandon the sql database. All your tables are now on elasticsearch. You can do search on whatever you want, but you must treat all your constraints manually.
2) Keep the structure on the sql database, you keep your three tables, the primary keys and the foreign keys. But your tables contains only elasticsearch ID of the associated row in elasticsearch. For exemple in table user, you keep user_id and add a user_elasticsearch_id that point on the elasticsearch row where you found the name, the email... etc... So you have your sql constraints, you can do search, but you must maintain two tables.
3) Duplicate. You don't touch your sql database, you duplicate all the rows on the elasticsearch database. You have your constrains, you can search, but again you must maintain two tables and you have twice the data and twice the storage.
Now, brave fellow of stackoverflow, what would you do in this case ?
Thank you.
The most common setup for critical business data is having e.g. a SQL database as your primary datastore and Elasticsearch as additional search index. (= your solution 3).
An alternative for non business-critical data like logs etc. is having Elasticsearch standalone.
Solution 2 seems wired, is not an option for me.
Because you may have a lot of business rules mixed into you database and application using it, I would be conservative and keep the DB. And use ES to index the user attributes I want to search on. ES would return scored results. When a result select I would switch to DB to retrieve all information and relations.
So I would choose 2b : keep DB and store PK in ES, not ID in DB).
Keep in mind you can force the ID en ES. It could be "user_PK" or something alike.

Trying to make my database more dynamic

I am trying to figure out what the best way to design this database would be. Currently what I have works, but it requires me to hard-code values where I would like it to be dynamic in the future.
Here is my current database design:
As you can see, for both the Qualities and the PressSettingsSet tables, there are many columns that are hard-coded such as BlownInsert, Blowout, Temperature1, Temperature2, etc.
What I am trying to accomplish is to have these be dynamic. Each job will have these same settings, but I would like to allow the users to define these settings. Would it be best to create a table with just a name field and have a one-to-one relationship to another table with a value for the field and a relation to the Job Number?
I hope this makes sense, any help is appreciated. I can make a database diagram of how I think it should work if that is more helpful to what I am trying to convey. I think that what I have in mind will work, but it just seems like it will be creating a lot of extra rows in the database, so I wanted to see if there is possibly a better way.
Would it be best to create a table with just a name field and have a one-to-one relationship to another table with a value for the field and a relation to the Job Number?
That would be the simplest - you could expand that by adding data-effective fields or de-normalize it by putting it all in one table (with just a name and value field).
Are the values for the settings different per job? If so then yes a "key" table" with the name ans a one-to-many relationship to the value per job would be best.

Mapping the fields of two database tables

The scenario is that, I have 2 database tables A and B. The table B is an upgraded version of the table A. (ie It might possibly have different field names and some extra fields). I need to compare these 2 tables to inform the user about these extra fields and propose to him a mapping of the fields between the tables.
Currently I am thinking of comparing them using info like field name, data element and domain in that order.
Is there a standard way to do this? Thanks in advance.
There is no standard tool to do this - why would you want to do it this way anyway? The canonical way is to extend the original table and fill the new fields in place.

Entity Framework : Table per Concrete Type and unique IDs across tables

I have a few tables that share only a few navigation properties and an ID.
I think Table per Concrete type inheritance would be interesting here.. (?)
It looks something like this :
Contact (Base, Abstract, not mapped)
- ContactID
- navigation properties to other tables (email, phone, ..)
Person : Contact (mapped to table Person with various properties + ContactID)
- various properties
Company : Contact (mapped to table Company with various properties + ContactID)
- various properties
Now for this to work, the primary key (contactID) should be unique across all tables.
2 options then:
- GUIDs (not a fan)
- an additional DB table generating identities (with just a ContactID field, deriving tables have FK), this would not be mapped in EF.
Is this setup doable ?
Also, what will happen in the ObjectContext ? What kind of temporary key does EF generate before calling SaveChanges ? Will it be unique across objects ?
Thanks for any thoughts.
mike.
We use a similiar construction with the folowing db design:
ContactEntity
ID
ContactPossibility
ID
Position
ContactTypeID
ContactEntityID
Address
ID (=PK and FK to ContactPossibility.ID)
Street
etc.
Telephone
ID (=PK and FK to ContactPossibility.ID)
Number
etc.
Person
ID (=PK and FK to ContactEntity.ID)
FirstName
etc.
Company
ID (=PK and FK to ContactEntity.ID)
Name
etc.
This results in the entity model in two abstract classes: ContactEntity (CE) & ContactPossibility (CP) and multiple derived classes (Address=CP, Email=CP, Person=CE, Company=CE). The abstract and derived classes (rows in the db ;) share the same unique identifier, because we use an ID field in derived classes that's a foreign key to the primary key of the abstract class. And we use Guid's for this, because our software has the requirement to function properly off-line (not connected to the main database) and we have to deal smoothly with synchronisation issues. Also, what's the problem with Guid's?
Entity Framework does support this db / class design very good and we have a lot of pleasure from this design.
Is this setup doable ?
Also, what will happen in the ObjectContext ?
What kind of temporary key does EF generate before calling SaveChanges ?
Will it be unique across objects ?
The proposed setup is very very doable!
The ObjectContext acts fine and will insert, update and delete the right tables for derived classes without effort. Temporary keys? You don't need them if you use the pattern of an ID for derived classes that is both primary key and foreign key to the abstract class. And with Guid's you can be pretty sure that's unique across objetcs.
Furthermore: The foreignKey from CP to CE will provide every CE (Person, Company, User, etc.) with a trackable collection of ContactPossibilities. Which is real cool and handy.
Hope this helps...
(not enough space in the comments section)
I've been running some tests.
The thing is you're OK as long as you ONLY specify the subtype you're querying for (ex. 'Address' in your case).
But if you query for the base type (even if you don't need the subtypes info), ex. only ContactPossibility.ID, the generated SQL will UNION all subtype tables.
So querying your 'trackable' collection of ContactPossibilities can create a performance problem.
I tried to work around this by unmapping the base entity and split the inherited entities to their own table + the common table, basically transforming the TPT into TPC : this worked fine from a conceptual perspective (after a lot of edmx editing). Until I realized this was stupid... :) Indeed in that case you will always need to Union all underlying tables to query for the common data...
(Though I'm not sure in the case described at the end of this post, didn't pursue to test it)
So I guess, since mostly I will need to query for a specific type (person, company, address, phone,..), it's gonna be OK for now and hoping MS will come with a fix in EF4.5.
So I'll have to be careful when querying, another interesting example :
Let's say you want to select a person and then query for his address, something like (tried to follow your naming) :
var person = from b in context.ContactEntities.OfType-Person-()
where b.FirstName.StartsWith("X")
select b;
var address = from a in context.ContactPossibilities.OfType-Address-()
where **a.ContactEntity == person.FirstOrDefault()**
select a;
this will produce a Union between all the tables of the Contact derived entities, and performance issues : generated SQL takes ContactPossibility table and joins to Address on ContactPossibilityID, then joins a union of all Contact derived tables joined with the base Contact table, before finally joining a filtered Person table.
However, consider the following alternative :
var person = from b in context.ContactEntities.OfType-Person-()
where b.FirstName.StartsWith("X")<BR>
select b;
var address = from a in context.ContactPossibilities.OfType-Address-()
where **a.ContactID == person.FirstOrDefault().ID**
select a;
This will work fine : generated SQL takes ContactPossibility table and joins to Address on ContactPossibilityID, and then joins the filtered Person table.
Mike.

Is there any way to fake an ID column in NHibernate?

Say I'm mapping a simple object to a table that contains duplicate records and I want to allow duplicates in my code. I don't need to update/insert/delete on this table, only display the records.
Is there a way that I can put a fake (generated) ID column in my mapping file to trick NHibernate into thinking the rows are unique? Creating a composite key won't work because there could be duplicates across all of the columns.
If this isn't possible, what is the best way to get around this issue?
Thanks!
Edit: Query seemed to be the way to go
The NHibernate mapping makes the assumption that you're going to want to save changes, hence the requirement for an ID of some kind.
If you're allowed to modify the table, you could add an identity column (SQL Server naming - your database may differ) to autogenerate unique Ids - existing code should be unaffected.
If you're allowed to add to the database, but not to the table, you could try defining a view that includes a RowNumber synthetic (calculated) column, and using that as the data source to load from. Depending on your database vendor (and the products handling of views and indexes) this may face some performance issues.
The other alternative, which I've not tried, would be to map your class to a SQL query instead of a table. IIRC, NHibernate supports having named SQL queries in the mapping file, and you can use those as the "data source" instead of a table or view.
If you're data is read only one simple way we found was to wrapper the query in a view and build the entity off the view, and add a newguid() column, result is something like
SELECT NEWGUID() as ID, * FROM TABLE
ID then becomes your uniquer primary key. As stated above this is only useful for read-only views. As the ID has no relevance after the query.