My table:
create table MyTable (
Id int identity(1,1) not null,
MyStatus char(2) not null
)
insert into MyTable(MyStatus) select 'A'
Class and enum:
public class MyTable
{
public virtual int Id { get; set; }
public virtual MyTableStatus MyStatus { get; set; }
}
public enum MyTableStatus
{
A,
B
}
Mapping:
public MyTableMap()
{
Id(x => x.Id);
Map(x => x.MyStatus);
}
When I execute the following test, I get System.FormatException : Input string was not in a correct format...
[Test]
public void Blah()
{
MyTable myTable = Session.Get<MyTable>(1);
Assert.That(myTable.MyStatus, Is.EqualTo(MyTableStatus.A));
}
What is the right way to map an enum to it's string representation in the database?
Edit - I am writing my application on an existing database, which I cannot modify easily because it is used by other applications also. So some fields in the database (which I would like to represent as enums in my application) are of type int and some of type char(2).
You need to create a custom IUserType to convert an enum to its string representation and back. There's a good example in C# here and an example in VB.NET for working with enums here (scroll down to implementing IUserType).
Well as far as I am aware NHibernate stores enums as string only in the db by default. I think I know what the problem here is. The way you are creating the table is incorrect.
if you are using Nhibernate use it build configuration function to create the tables instead of creating the tables manually and then you will see that your enum is stored as string.
We use enums extensively in our app and it makes sense for us to store it as strings in the db. The reasons are simple if I add a new value to an enum tom then if default values are not set then my code and my data are tightly coupled which I definitely wouldnt want.
SimpleConfig.ExposeConfiguration(c => new SchemaExport(c).Create(false, true)).BuildConfiguration();
Also instead of using char for your string can you use varchar for the property.
After the update:
Cant you guys do some kind of manipulation before you store it in the database? Thus when you want to store the new char enums write a function that generates an int value for you and store this in the propertry and now save it or if you want to make it simple the function can have a switch case.
So what you do is you dont have a get on this property that is retrieved from the db instead you add a new property in the class Status that basically has the logic of getting the appropriate enum.
Do you think thats a good idea?
Hope this helps.
Related
It seems sorting in Dapper Extensions can be achieved with Predicates:
Predicates.Sort<Person>(p => p.LastName)
My question is, how do I implement random sorting (i.e. RAND() in sql) to predicates?
Predicates.Sort actually produces an ISort-compatible interface which is defined as follows:
public interface ISort
{
string PropertyName { get; set; }
bool Ascending { get; set; }
}
It looks like we have a chance of setting property name to "RAND()" or something, right?... But, sadly, this interface is used in this way:
if (sort != null && sort.Any())
{
sql.Append(" ORDER BY ")
.Append(sort.Select(s => GetColumnName(classMap, s.PropertyName, false) + (s.Ascending ? " ASC" : " DESC")).AppendStrings());
}
So Dapper Extensions in fact check that the passed name is a column name. And the GetColumnName is defined as follows:
public virtual string GetColumnName(IClassMapper map, string propertyName, bool includeAlias)
{
IPropertyMap propertyMap = map.Properties.SingleOrDefault(p => p.Name.Equals(propertyName, StringComparison.InvariantCultureIgnoreCase));
if (propertyMap == null)
{
throw new ArgumentException(string.Format("Could not find '{0}' in Mapping.", propertyName));
}
return GetColumnName(map, propertyMap, includeAlias);
}
Therefore, the string actually should be not a column name, but a property name (they have named the field in ISort interface for a purpose, right?).
So, to implement something like the thing you want you need to customize their SQL generator.
For further details, the best way is to refer to sources:
Predicates: https://github.com/tmsmith/Dapper-Extensions/blob/master/DapperExtensions/Predicates.cs
SqlGenerator: https://github.com/tmsmith/Dapper-Extensions/blob/master/DapperExtensions/Sql/SqlGenerator.cs
PS: I am unable to post link to the repo root due to beginner's rep, hope you can guess it ;)
PPS: The same is true for whole predicates system in Dapper Extensions. I believe it should be greatly refactored to allow more than plain-forward column-based restrictions.
I'm using the Azure Mobile Service for a Windows Phone 8 project.
I am trying to store complex types in my database and therefore use json.net's JsonConverter.
My data-class looks like this:
public class Data
{
...
[JsonConverter(typeof(MyConverter))]
public ComplexType SomeMember{get;set;}
...
}
That seems to work fine, but there is one problem:
I want to map the 'Data'-class to a database table with a different name, like 'data_something'
This can be achieved by using
[DataContract(Name="data_something")]
public class Dat
{
...
}
But then the Json.NET Annotations are ignored.
Is there a way to use Json.NET and specify the Table-Name separately?
Or perhaps another way to use Azure Mobile to get the right table even if the class name is not the same. (I'm currently using dataTable= MobileService.GetTable<Data>();)
You can use the [DataTable] attribute for that:
[DataTable("data_something")]
public class Data
{
[JsonConverter(typeof(MyConverter))]
public ComplexType SomeMember { get; set; }
// other members ommitted
}
whats difference between Auto-Implemented Properties and manual properties in c#?
for Example:
Manual Properties:
private int uno;
public int Uno
{
get { return uno; }
set { uno = value; }
}
Auto Implemented Prop:
public string UserLeaveCount { get; set; }
i found the difference and uses here : Auto Implemented Prop
But Here is my Specific doubt thats "there is no instance variable in auto implemented properties and how is it stored,returned values?"
It's just syntactic sugar -- the compiler inserts the backing field for you. The effect is the same, except that, of course, there's no way for you to access the backing field from your code.
From the page you linked to:
When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.
I have a DocumentDataServiceContext derived from TableServiceContext. Inside that class I have the following method:
public DataServiceQuery<Document> Documents
{
get
{
return this.CreateQuery<Document>("Documents");
}
}
Is there a way to get rid of the string constant passed to CreateQuery and instead obtain the table name used by CloudTableClient.CreateTablesFromModel(typeof(DocumentDataServiceContext))?
No. At the end of the day, the CreateQuery() must have the table name to query against. You can of course use convention or reflection to derive what that table name will be in another method, but at some point a string must be passed to CreateQuery.
public DataServiceQuery<T> CreateQueryByConvention<T>()
{
return this.CreateQuery<T>(typeof(T).ToString());
}
There are a lot of workarounds for the missing support of enumerations in the Entity Framework 4.0. From all of them I like this one at most:
http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx?PageIndex=2#comments
This workaround allows you to use enums in your LINQ queries which is what i exactly need. However, I have a problem with this workaround. I get for every complex type I'm using a new partial autogenerated class.Therefore the code does not compile any more because I already have a wrapper class with this name in the same namespace which converts betwen the backed integer in the database and the enum in my POCO classes. If I make my wrapper a partial class, the code still does not compile as it now contains two properties with the same name "Value". The only possibility is to remove the Value property by hand everytime I generate the POCO classes because the DB model changed (which during the development phase happens very often).
Do you know how to prevent a partial class to be generated out of complex property everytime the EF model changes?
Can you recommend me some other workarounds supporting enumerations in LINQ queries?
That workaround is based on the fact that you are writing your POCO classes yourselves = no autogeneration. If you want to use it with autogeneration you must heavily modify T4 template itself.
Other workaround is wrapping enum conversion to custom extension methods.
public static IQueryable<MyEntity> FilterByMyEnum(this IQueryable<MyEntity> query, MyEnum enumValue)
{
int val = (int)enumValue;
return query.Where(e => e.MyEnumValue == val);
}
You will then call just:
var data = context.MyEntitites.FilterByMyEnum(MyEnum.SomeValue).ToList();
I am using an approach based on the one described in your link without any modifications of the T4 templates. The contents of my partial wrapper classes are as follows:
public partial class PriorityWrapper
{
public Priority EnumValue
{
get
{
return (Priority)Value;
}
set
{
Value = (int)value;
}
}
public static implicit operator PriorityWrapper(Priority value)
{
return new PriorityWrapper { EnumValue = value };
}
public static implicit operator Priority(PriorityWrapper value)
{
if (value == null)
return Priority.High;
else
return value.EnumValue;
}
}
I've only changed that instead of a back store variable with enum value I am using the autogenerated int typed Value property. Consequently Value can be an auto-implemented property and EnumValue property needs to do the conversion in getter and setter methods.