I can't have [.] (periods) in my key names (Indexes, primary keys and foreign keys) when they are generated by Add-Migration, so I tried to write a CSharpMigrationCodeGenerator, but unfortunately this doesn't seem to allow you to change the foreign keys or index names. The primary key name can be set as part of overriding the create table:
protected override void Generate(
CreateTableOperation createTableOperation, IndentedTextWriter writer)
{
createTableOperation.PrimaryKey.Name = "USE THIS NAME";
base.Generate(createTableOperation, writer);
}
But what I really need is a way to ensure that it has just removed full stop (which implies overriding the custom name generator) - but I can't see how to do this.
Have you not tried retrospectively generating code first with the power tools?
Not only would it generate code first classes for you from the database, you can also customize the T4 templates that generate your objects in order to handle unique scenarios (for example custom naming logic to handle reserved characters). My entity.tt has the following above each generated object:-
[MetadataType(typeof(<#= efHost.EntityType.Name #>_Validation))]
This means I can have all my data validation farmed off into a separate class that isn't overridden upon re-creation of my objects.
this issue no longer exists and was quite specific at the time. Things have moved on with tooling over the last year and therefore isn't really relevant anymore as you wouldn't need to solve the issue this way.
Many thanks for reading and commenting
by entity framework code first migration you can change the foreign keys or index names, you can see in the example in here:
http://msdn.microsoft.com/en-us/data/jj591621.aspx
http://www.dotnetcurry.com/showarticle.aspx?ID=889
Related
I am working on a simple database and to be specific here is the model generated by database first approach (Visual Studio 2017 Community, Entity Framework 6.2):
Generated Database Model
I'd like the UserMessage table to be able to point to itself with a field named AnswerId, this is a nullable foreign key referencing its primary key. Again, to be specific, here is the part where I create the table:
UserMessage table script
My problem is that when Entity Framework generates the classes based on the existing database everything goes fine except for this particular table, in which EF suggests (I don't know why) that the UserMessage table has a multiplicity of 0..1 - * to itself while it should 1 - 0..1 (because a message may have a direct answer, but not more than 1, though that message, which is the answer, could also have an answer, so it's just like a linked list).
Here is the generated class: UserMessage generated class
To sum up the whole thing: I'd like to know why Entity Framework generates my class the way it does, and how could I make it generate it so that I only have a virtual property pointing to the answer (in case it has one), but not a collection.
Thank you for your answers!
I think what you're seeing is a correct interpretation by EntityFramework.
UserMessage1 represents a collection of all the UserMessages that have references to the parent as their answer. I understand that you probably won't use that collection for anything but it's not wrong that it's there. UserMessage2 seems to be the property you're looking for. Maybe you could rename those properties in the diagram so they're not confusing.
UserMessages1 = MessagesThatReferenceMe
UserMessages2 = the Message that I may or may not reference
I don't see how you can stop EF from generating this collection. I think if you delete the property in the diagram you will have to delete it every time you update the diagram.
Maybe try deleting the 2nd UserMessage navigation property in your model.
I choose Database First:
Here is an example table that is experiencing this issue. As you can see the EntityId column is the Primary Key:
The imported table in the model browser shows that it has the Primary Key:
But the code for the generated class does not have the EntityId column decorated with a Key attribute:
At run time I get this error:
Additional information: One or more validation errors were detected
during model generation: EntityType 'Entity' has no key defined.
Define the key for this EntityType.
Why do I have to manually decorate the EntityId column with the Key Attribtue? Shouldnt EntityFramework take care of all that considering it is Database first?
Typically speaking I have experience with EF4 through EF 6.1.3 and a teeny bit with Entity Core (was EF7 and then MS fun with naming). Typically if you are doing database first you do not get an adornment from your t4 template. I just looked at mine just now and I have no adornment for the key, just for constructor and the reference to the navigation of teOrder back to it.
I can save an Entity just fine and my code runs with this:
using (var context = new EntityTesting.TesterEntities())
{
var nPerson = new tePerson { FirstName = "Test", LastName = "Tester" };
context.tePerson.Add(nPerson);
context.SaveChanges();
}
What I would suggest is:
Go to your (name).edmx Entity File and on the design surface wipe out the object and then replace it on the surface. In countless times this has fixed issues with the generated objects. When you SAVE it should auto run the T4 templates (*.tt files). If not you can select them, right click and select 'Run Custom Tool'. This just generates the POCO objects or the Context objects.
If this is really a fault with the table it is typically with it NOT having a key. You are showing it does though. Is there anyway to mirror the exact same table logic and confirm the key has nothing out of the ordinary and is just a plain old key Primary Key?
Create a brand new table with similar structure but not an exact copy and a new Entity File and confirm you can create it.
Tables are pretty straight forward with EF, or as straight forward as EF can be. You create them in SQL, ensure you have a key, add it to a design surface, save, it generates the objects for you. If you have other things under the hood like custom procs hooked to it or other out of the ordinary nav items that would be one thing. The only other thing would be if it has a very old SQL Type as the key. I know that the 'Text' type and EF do not play nice together. There may be other types that behave the same way.
This issue was fixed by including the "metadata" part of the connection string.
At first my connection string looked like this:
data source=.;initial catalog=TestDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework;
Which produced the error.
Changing my connection string to this:
metadata=res://*/DbContexts.TestContext.csdl|res://*/DbContexts.TestContext.ssdl|res://*/DbContexts.TestContext.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=TestDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"
Allowed operations on the Context to be performed with no error encountered
I am working with DAL2 in DNN 7+.
I have a database table with a primary key created from 2-varchar(50) fields.
What is the proper way to declare the multi-field primary key in the attributes of the object?
I typically do:
[PrimaryKey("myField")]
Should I just add a second PrimaryKey attribute?
The second part of the question is how to get the data out of the database.
I would like to use the GetById() function because it incorporates caching but it doesn't appear to support multiple fields. Am I stuck using the Find() method and handling caching manually or what is the best way to select objects that use a multiple field primary keys?
"Look to the sky as much as the screen!"
DAL2 does not support Composite Keys.
The best way I have found to work around this limitation is to modify the database table. I use an Auto-increment int 'id' field for the primary key and set a unique constraint on the fields that I desired to use as the composite key.
This will required the .Find() method to be used which prevents caching. If caching is desired it must be done manually. When cache is manually set, it should be manually cleared as well. If you are using the repository technique make sure to clear the cache when the object is updated, or deleted.
"Look to the sky as much as the screen!"
I am using EntityFramework version 4.4, code first and I have created my data model in a separate project (MyApp.DataModel).
Because I am building a Silverlight application, I am using a WCF RIA services. The code required by the ria services is in a different project (MyApp.Services). This project has a reference to MyApp.DataModel.
An example of an data model:
[Column("Remaining")]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public virtual decimal? Remaining
{
//
}
When I build MyApp.Services I get an error
Duplicate 'System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute' attribute
Indeed, in the generated code there are two attributes
[System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Computed)]
[System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Computed)]
If I remove DatabaseGenerated, then on insert I get an error
The column "Remaining" cannot be modified because it is either a computed column or is the result of a UNION operator.
Any idea why and how to solve this problem?
As far as I understand the documentation here: http://msdn.microsoft.com/en-us/data/gg193958.aspx , Key already defaults to DatabaseGeneratedOption.Identity, so you wouldn't need to add the DatabaseGenerated separately.
Excerpt from the part under DatabaseGenerated:
a key property will become an identity key in the database. That would
be the same as setting DatabaseGenerated to
DatabaseGenerationOption.Identity. If you do not want it to be an
identity key, you can set the value to DatabaseGenerationOption.None.
To be honest, I haven't tested this, but can you confirm that after removing [DatabaseGenerated(DatabaseGeneratedOption.Identity)] , the other attribute still remains in the generated code?
If you mark the property as DatabaseGeneratedOption.Identity the EF understand that this is the key attribute.
Actually if you don't place none attribute (Key or DatabaseGeneratedOption.Identity) the EF will assume that this is the id as the property ends with 'ID' and will create a autoincrement field at database.
The DataAnnotations are optional in many cases (like yours).
You also don't need to mark this property as virtual as it's a primitive type. Use virtual just to associate others classes (lazy load).
I'm using generated POCO classes and Entity Framework.
In order to make the code less complex I'm trying to remove all navigation properties from the code while still keeping the Foreign Key constraints in the database (navigation properties do more harm than good for us).
If I remove them manually from the POCO-classes I get the following error
The entity type UserEntity is not part of the model for the current context
If I try to remove them from the .edmx-file I get the following error:
Error 3 Error 3015: Problem in mapping fragments starting at lines 479, 562:Foreign key constraint 'fk_StorageContracts_User1' from table StorageContract (OwnerUserID) to table User (ID):: Insufficient mapping: Foreign key must be mapped to some AssociationSet or EntitySets participating in a foreign key association on the conceptual side.
Is there any way to remove navigation properties from POCO-classes without removing the corresponding FK?
I know this is old, but, since there is still no answer, I thought I'd give it a try:
I am still working in EF 4.0, but, following the example to which you referred, you have an xxxModel.tt. If you are willing to tweak that, you can find where it generates the Navigation Properties and change them to be simple auto-properties. I had a similar project where I generated them like this:
public List<NavDataX> NavDataXs
{
get; set;
}
Now, they are still there, but they are null until you explicitly set them. Doing it this way, I did not mess with the EDMX and did not encounter the two errors you mentioned.