Good day,
I have been learning some Entity Framework and I came to this code
public class Test
{
public int Id { get; set; }
public string name { get; set; }
public testEnum testEnum { get; set; }
}
public enum testEnum {
numero1=1,
numero2=2
}
Then I run add-migration xxxxx and update-database, the problem is that when I go to SQL server, I can not see the enum anywhere.
My questions are:
1.What happened with the enum and how can I see it in SQL server?
2. When do I use enum instead of a table like the following:
public class EnumReplace{ public int Id { get; set; }
public int value{ get; set; }
}
thank you.
1.What happened with the enum and how can I see it in SQL server?
The enum gets stored in the database table as an integer. You wouldn't be able to see the enumeration in the database. EF takes the responsibility of casting the underlying type to the enumeration defined while retrieving the values from the database.
In Entity Framework, an enumeration can have the following underlying types: Byte, Int16, Int32, Int64 , or SByte.
Read more about enum support in EF code first here
2. When do I use enum instead of a table like the following:
When we have a predefined set of values allowed for a property/field, we usually use enumeration. For e.g.
enum Days
{
Sat,
Sun,
Mon,
Tue,
Wed,
Thu,
Fri
};
You could also use Flagged Enums, Read more about enum here.
you have to have the enum in your class. something like this:
public testEnum MyProperty{ get; set; }
so basically you can't have enum as a table. you can have enum as a type of one of your properties in a table.
Related
I got the following types
internal enum IssueType
{
First,
Second,
Special
}
internal class Issue
{
public int Id { get; set; }
public string Title { get; set; }
public IssueType Type { get; set; }
}
internal class SpecialIssue : Issue
{
public string Payload { get; set; }
}
Some issue types map to certain subclasses, like Special would map to SpecialIssue in this case. Others just map to Issue i.e. there are several IssueTypes without special subclasses.
Now I would like to have an Issues table to hold all these issues so I configured Issue.Type as a discriminator value.
builder.HasDiscriminator(x => x.Type)
.HasValue<Issue>(IssueType.First)
.HasValue<Issue>(IssueType.Second)
.HasValue<SpecialIssue>(IssueType.Special);
Unfortunately it seems that I cannot set multiple discriminator values for the same type so at runtime I get errors stating that some discriminators weren't mapped although I did.
What I would like to achieve is to map all subclasses to their respective discriminators and have some kind of "fallback" that maps to Issue (or just map any remaining IssueType to the Issue type manually).
Is it possible to achieve this? I couldn't figure out any way to get EFCore to do this.
I'm currently using EFCore 5.0.10.
I have postgres database with some data in it.
I'm using Npgsql.EntityFramework7 adapter (version 3.1.0-beta8-2) to handle it.
The problem is when I try to get entity from context which has some enum inside of it.
In postgres I declare enum:
CREATE TYPE public.my_enum AS
ENUM ('value1','value2','value3');
My model looks like:
[Table("my_table")]
public class Entity
{
[Column("id")]
[Key]
public int Id { get; set; }
[Column("type")]
public MyEnum Type { get; set; }
}
Enum:
public enum MyEnum
{
value1,
value2,
value3
}
Unfortunately, when I try to get something from database via entity framework I receive this kind of error:
System.InvalidCastException: Can't cast database type
my_enum to Int32
I've tried to register my enum in Npgsql (as it's pointed in npgsql documentation). With no effects.
Is there something I can do to handle 'proper' enums with this stack? (to have enum fields in database as strings/enums not as ints)
We have been using EF CF for a while in our solution. Big fans! Up to this point, we've been using a hack to support enums (creating an extra field on the model; ignore the enum durring mapping; and map the extra field to the column in the db that we would have used). Traditionally we have been storing our enums as strings(varchars) in the DB (makes it nice and readable). Now with enum support in EF 5 (Beta 2) it looks like it only supports mapping enums to int columns in the DB....Can we get EF 5 to store our enums as their string representation.
Where "Type" is an enum of type DocumentType
public enum DocumentType
{
POInvoice,
NonPOInvoice,
Any
}
I tried to map it using:
public class WorkflowMap : EntityTypeConfiguration<Model.Workflow.Workflow>
{
public WorkflowMap()
{
ToTable("Workflow", "Workflow");
...
Property(wf => wf.Type).HasColumnType("varchar");
}
}
I thought was going to be the magic bullet but..
That just throws:
Schema specified is not valid. Errors: (571,12) : error 2019: Member
Mapping specified is not valid. The type
'Dodson.Data.DataAccess.EFRepositories.DocumentType[Nullable=False,DefaultValue=]'
of member 'Type' in type
'Dodson.Data.DataAccess.EFRepositories.Workflow' is not compatible
with
'SqlServer.varchar[Nullable=False,DefaultValue=,MaxLength=8000,Unicode=False,FixedLength=False]'
of member 'Type' in type 'CodeFirstDatabaseSchema.Workflow'.
Your thoughts?
This is currently not possible. Enum in EF has same limitations as enums in CLR - they are just named set of integer values. Check this article for confirmation:
The EF enum type definitions live in conceptual layer. Similarly to
CLR enums the EF enums have underlying type which is one of Edm.SByte,
Edm.Byte, Edm.Int16, Edm.Int32 or Edm.Int64 with Edm.Int32 being the
default underlying type if none has been specified.
I posted article and related suggestion about this problem. If you want to see this feature in the future please vote for the suggestion.
I hit this problem a few weeks ago. The best I could come up with is a bit hacky.
I have a Gender enum on the class Person, and I use data annotations to map the string to the database and ignore the enum.
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Column("Gender")]
public string GenderString
{
get { return Gender.ToString(); }
private set { Gender = value.ParseEnum<Gender>(); }
}
[NotMapped]
public Gender Gender { get; set; }
}
And the extension method to get the correct enum from the string.
public static class StringExtensions
{
public static T ParseEnum<T>(this string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
}
See this post for full details - http://nodogmablog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/
I am trying to build a data structure that can store the trial by trail results of a group of different tests I am running. The test all consist of a number of trails but some of the information that I want to save and later use is different for the different tests. For example, the results of TestA might look like:
Trial(int) WasResponseCorrect(bool) WhichButtonWasPressed(string) SimulusLevel(double)
1 false "Up" 3.5
2 true "Left" 6.5
Where TestB might have different types of result fields:
Trial(int) WasResponseCorrect(bool) ColorPresented(string) LetterPresented(char) LetterGuessed(Char)
1 false green G C
2 false blue H F
I was thinking of creating a dictionary with the field names as the keys (ex. WasResponseCorrect) and an array of the field values as the values of dic. I can't figure out how to do that. Maybe there is a better way to store the information but I can't think of how to do it. I am working with .net (VB and C#) but I think I can understand and convert most any code if you know of examples in other languages. Thanks!
Without knowing more about your requirements (how you are going to store the data, for example), it seems like polymorphism is what you're looking for. That is, you have a superclass (called Trial) and subclasses that represent the specific trial types. For example:
public class Trial {
public int Id { get; set; }
public bool WasResponseCorrect { get; set; } // if this is in every type of trial
// anything else that is common to ALL trial types
}
public class TrialA : Trial {
public string WhichButtonWasPressed { get; set; }
public double SimulusLevel { get; set; }
}
public class TrialB : Trial {
public string ColorPresented { get; set; }
public char LetterPresented { get; set; }
public char LetterGuessed { get; set; }
}
That way you can have a list of Trial objects, but the actual runtime type of those objects can be TrialA or TrialB.
Here is the code I would like to use:
public enum Days { Sat = 1, Sun, Mon, Tue, Wed, Thu, Fri };
[EnumHelper(typeof(Days))]
public Days DayOfWeek { get; set; }
EnumHelper looks like:
[AttributeUsage(AttributeTargets.Property,AllowMultiple=true)]
public class EnumHelper : Attribute
{
public Type MyEnum { get; set; }
public EnumHelper(Type enum)
{
MyEnum = enum;
}
}
The error I get on EnumHelper(Days) is that "Enum Name not valid at this point". Am I doing something wrong, or can this not be done?
MORE INFO
I am trying to pass the Enum (Days), and randomly get back one of the values.
You're trying to pass a type name as if it were an argument value. You can't do that. However, you can do:
[AttributeUsage(AttributeTargets.Property,AllowMultiple=true)]
public class EnumHelper : Attribute
{
public Type EnumType;
public EnumHelper(Type enumType)
{
EnumType = enumType;
}
}
...
[EnumHelper(typeof(Days))]
public Days DayOfWeek { get; set; }
However:
I wouldn't personally make EnumType a public field; make it a property.
There's currently no validation that EnumType is actually an enum. You can't do it at compile-time, but you could do it at execution time.
For the sake of convention, it should be called EnumHelperAttribute (or something more descriptive, really) - this isn't causing the error, but it's more idiomatic
I'm not really sure I see the benefit... you can find the type of the property from the metadata already; what do you think the attribute is actually buying you?
If you could let us know what you're trying to accomplish, we may be able to be more useful to you.
The parameters in Attributes can be only constants.
If you want pass the enum type you must pass only the type:
[EnumHelper(typeof(Days))]
public Days DayOfWeek { get; set; }
[AttributeUsage(AttributeTargets.Property,AllowMultiple=true)]
public class EnumHelper : Attribute
{
public Type MyEnum;
public EnumHelper(Type enum)
{
MyEnum = enum;
}
}
The parameter should be an enum value, not an enum type, like:
[EnumHelper(Days.Sat)]
Just wanted to add how I ran into this and fixed it. I had my property named the same as my enumeration. The code would compile and run, but I was getting a the red line error message in the IDE. Changing the name of the property to something unique cleared the message.