I have a prolem when use Enum for Database first.
I have two table:
Table1:
Id int
Label nvarchar(50)
StatusId int
Table2:
StatusId
Label
I created a Constrains key for two table, and in Asp Mvc. i load both into a Model.edmx. so I want to convert StatusId in Table1 to an enum for easy operation, but i cannot do it.
What is wrong? How can i do it? I don't want to remove Table2 from Model.
Thank in advance!
enum is implemented in the CLR as an int32, but it is not an int32. It is a separate type, so you cannot use in the Entity Framework. But could use it to reference an int32 in the other entity.
I would rather suggest to go Code First Approach for implementing your ideas.
Use this link for details and samples about Code First Approach
Related
I'm modeling an application in F# and I encountered a difficulty when trying to construct the database tables for the following recursive type :
type Base =
| Concrete1 of Concrete1
| Concrete2 of Concrete2
and Concrete1 = {
Id : string
Name : string }
and Concrete2 = {
Id : string
Name : string
BaseReference : Base }
The solution I've got for the moment (I've found inspiration here http://www.sqlteam.com/article/implementing-table-inheritance-in-sql-server) is :
I have two concerns with this solution :
There will be rows on the Base table even though that doesn't make sense in my model. But I can live with that.
It seems that queries to find all the information about BaseReference of Concrete2 will be complex since I will have to take into account the recursivity of the type and the different concrete tables. Moreover, adding a new concrete type to the model must modify these queries. Unless of course there is an equivalent to the match F# keyword in SQL.
Am I worrying too much about these concerns? or maybe, is there a better way to model this recursive F# type in SQL tables?
Part 1: Encoding Algrebraic Data Types in Relational Tables
I've struggled with this very thing many times. I finally discovered the key to modeling algebraic data types in relational tables: Check constraints.
With a check constraint, you can use a common table for all members of your polymorphic type yet still enforce the invariant of each member.
Consider the following SQL schema:
CREATE TABLE ConcreteType (
Id TINYINT NOT NULL PRIMARY KEY,
Type VARCHAR(10) NOT NULL
)
INSERT ConcreteType
VALUES
(1,'Concrete1'),
(2,'Concrete2')
CREATE TABLE Base (
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
ConcreteTypeId TINYINT NOT NULL,
BaseReferenceId INT NULL)
GO
ALTER TABLE Base
ADD CONSTRAINT FK_Base_ConcreteType
FOREIGN KEY(ConcreteTypeId)
REFERENCES ConcreteType(Id)
ALTER TABLE Base
ADD CONSTRAINT FK_Base_BaseReference
FOREIGN KEY(BaseReferenceId)
REFERENCES Base(Id)
Simple, right?
We've addressed concern #1 of having meaningless data in the table representing the abstract base class by eliminating that table. We've also combined the tables that were used to model each concrete type independently, opting instead to store all Base instances--regardless of their concrete type--in the same table.
As-is, this schema does not constrain the polymorphism of your Base type. As-is, it is possible to insert rows of ConcreteType1 with a non-null BaseReferenceId or rows of ConcereteType2 with a null BaseReferenceId.
There is nothing keeping you from inserting invalid data, so you'd need to be very diligent about your inserts and edits.
This is where the check constraint really shines.
ALTER TABLE Base
ADD CONSTRAINT Base_Enforce_SumType_Properties
CHECK
(
(ConcreteTypeId = 1 AND BaseReferenceId IS NULL)
OR
(ConcreteTypeId = 2 AND BaseReferenceId IS NOT NULL)
)
The check constraint Base_Enforce_SumType_Properties defines the invariants for each concrete type, protecting your data on insert and update. Go ahead and run all the DDL to create the ConcreteType and Base tables in your own database. Then try to insert rows into Base that break the rules described in the check constraint. You can't! Finally, your data model holds together.
To address concern #2: Now that all members of your type are in a single table (with invariants enforced), your queries will be simpler. You don't even need "equivalent to the match F# keyword in SQL". Adding a new concrete type is as simple as inserting a new row into the ConcreteType table, adding any new properties as columns in the Base table, and modifying the constraint to reflect any new invariants.
Part 2: Encoding hierarchical (read: recursive) relationships in SQL Server
Part of concern #2 I think about the complexity of querying across the 'parent-child' relationship that exists between ConcreteType2 and Base. There are many ways to approach this kind of query and to pick one, we'd need a particular use case in mind.
Example use case: We wish to query every single Base instance and assemble an object graph incorporating every row. This is easy; we don't even need a join. We just need a mutable Dictionary<int,Base> with Id used as the key.
It would be a lot to go into here but its something to consider: There is a MSSQL datatype named HierarchyID (docs) that implements the 'materialized path' pattern, allowing easier modeling of hierarchies like yours. You could try using HierarchyID instead of INT on your Base.ID/Base.BaseReferenceID columns.
I hope this helps.
I am currently using a Dbsetlist.Count() to get the primary key of an Autoincremented table where an Row will be saved before any actual saving is performed.. But I feel this approach is not correct but cannot figure out any other alternative purely using Linq can someone suggest how to do this in Linq only?
db.Invoicesets.Add(invoice); //Invoicesets is Invoice table as list for Linq
order.invno = db.Invoicesets.Count(); // Invno is needed as a foreign for Order table
db.Ordersets.Add(order); //
db.SaveChanges();
Do you mean, say, you want to add entity A first so you can use the identity column of A, A.ID as the FK to entity B? If yes, you can use InsertOnSubmit():
db.Invoicesets.InsertOnSubmit(invoice);
order.invo = invoice;
db.orders.InsertOnSubmit(order);
db.SubmitChanges();
You want to be very careful here. What happens if two threads, at the same time, execute:
order.invno = db.Invoicesets.Count();
You will have two orders with the same invno field, which is probably something you don't want.
I'm guessing that field should have a unique constraint on it, and is perhaps your primary key? I don't think there is any LINQ only way to do this, I think you need to make invno an Identity column, that way you'll be assured that it will increment and remain unique.
EDIT
As an aside, you could also generate a GUID for invno in your application code, but obviously you'll have to change the datatype of the invno field in your db.
Im my model, Is it best to use an int or a number of bools to store each RadioButtons state?
I see examples using int, id prefer to use a bool for each rdo button for ease of searching in Linq2Sql.
Whats the best practice?
A radio button group represents a single property that can have one of many values.
Therefore, int is a more logical choice than bool.
Perhaps a set of flags would better describe your model? In that case, [Flags] Enum would be an excellent model.
Finally, if your data is stored as a set of bool values, then a group of checkboxes would make more sense.
I know this should not be trivial, but so far couldn't find the resolution...
Working with an EF4 DB-First model, using LINQ-to-Entities with POCOs which will be consumed by an MVC3 app.
I have three entities Customer, CustomerAdress and a lookup CustomerAddressType.
Customer CustomerAddress CustomerAddressType
---------- ---------------- -------------------
CustomerId (PK) CustomerAddressId (PK) CustomerAddressTypeId (PK)
LastName CustomerId (FK) Description (Values: Mailing, Billing)
FirstName CustomerAddressTypeId (FK)
MiddleInitial Address
.... City
State
Zip
StartDate
EndDate
As you can see CustomerAddress has a FK CustomerAddressTypeId, which identifies what type of address this is, i.e. Mailing or Billing.
I would like to:
Have is ability to do something like this: Customer.CustomerAddress.OfType<MailingAddress> to get the collection of mailing addresses for the customer.
Have a CurrentMailingAddress and CurrentBillingAddress properties, that would return the single instance CustomerAddress.OfType<> with the highest StartDate and EndDate in the future.
Would be also nice to take Address thru Zip properties and refactor those propertiess into a Complex Type Address.
I tried creating 2 inherited entities off of CustomerAddress (assuming it is TPH [table-per-hierarchy] strategy):
MailingAddress and BillingAddress, CustomerAddressTypeId being the discriminator. I did this in the model designer, and as soon as I tried adding a second inherited entity, it told me that the properties with those names already existed, and wouldn't let me rename them to match the properties of the first entity.
Any ideas how to accomplish this? Please dumb it down for me :)
Thanks!!!
It is not such trivial. TPH will be possible but you must place all properties to the base CustomerAddress and derive two sub entities which will not hold any property because all properties are shared (= must be in the parent). You will use CustomerAddressTypeId as discriminator and because of that you will not be able to map this field as property in the entity. I'm also not sure if you can have the field both in discriminator and association mapping (that is actually nice homework for me). If not you will not be able to map association between CustomerAddress and CustomerAddressType.
Both CurrentMailingAddress and CurrentBillingAddress are computed properties and they are not part of mapping. It is up to you to implement their logic in your partial part of Customer entity.
I don't understand the last point with Zip and complex type.
I have the following Models
DeltaDirectionType,
int Id
string Name
Delta,
int Id
string Name
DeltaDirectionType DeltaDirectionType
Double Value
Trade
int Id
DateTime BusinessDate
IList<Delta> deltas
So DeltaDirectionType is a lookup table, Trade holds a collection of Deltas
In the database it is implemented as follows
DeltaDirectionTypes
Id int
Name varchar(max)
Deltas
Id int
Name varchar(max)
DeltaDirectionType_Id int
Trade_Id int
Value float
Trades
Id int
BusinessDate DateTime
Delta_Id int
When I generate the model from code for the Edmx file, and (un check the foreign keys) as my model does not have properties for these. I am having problem with the navigation properties. Something like this in nHibernate would be a simple one to many mapping for the DeltaDirectionType and Delta and a many to many for Delta and Trades however, how do I firstly get it to recognise that DeltaDirectionType is a lookup and secondly get the Icollection to work for me.
I am struggling with this, Entity Framework does not make it easy for you. I have tried the usual, delete the navigation property that EF puts in for you on one side, but then you get some mapping fragments errors, properties not mapped etc.
Please help or point in the right direction.
Lookup tables are real life problems, not sure why it is so hard withing EF to implement.
Any help much appreciated
Thanks
You must either create foreign keys or navigation properties in the model to navigate the relationship.
Navigation properties can be defined as one-way, ie from the deltas table to the look-up table. A one-way navigation like this would add the appropriate property to the delta's object but not to the looup table
What you actually mean by lookup? Do you except that Delta entity will have DeltaDirectionType_Name directly mapped?
In EF you will get navigation property to DeltaDirectionType and you can access the name through this navigation property. If you don't like it you can add new property to partial class of your generated POCO and provide the Name directly in Delta entity like:
public string DeltaDirectionTypeName
{
get
{
return DeltaDirectionType != null? DeltaDirectionType.Name : String.Empty;
}
}
The only problem is that you can't use this property in Linq-To-Entities queries. In queries you always have to use navigation properties.