According to Microsoft:
http://msdn.microsoft.com/de-de/library/system.data.linq.mapping.columnattribute.expression.aspx
It's possible to add expression to the Linq-to-SQL Mapping.
But how to configure or add them in Visual Studio in the Designer?
Problem, when I add it manual to thex XYZ.designer.cs it on change it will be lost.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4927
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
This is generated:
[Column(Name="id", Storage="_id", DbType="Int")]
public System.Nullable<int> id
{
...
But i need something like this
[Column(Name="id", Storage="_id", DbType="Int", Expression="Max(id)")]
public System.Nullable<int> id
{
...
Thanks.
According to this article:
http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.columnattribute.expression.aspx
you should use the ColumnAttribute.Expression Property when you use CreateDatabase to define a column as containing computed values.
So you should check this article:
http://msdn.microsoft.com/en-us/library/Bb399420%28v=VS.100%29.aspx
Another way is to define expression on your sql server so it'll be mapped by the LINQ designer.
Edit: mmmm you edited your question, so probably my answer is not gonna help you so much, but you might be able to do this anyway with your 'extended' question :D
I do this by adding another class file to the project, give them the same name as the object from LinQ-to-SQL you want to extend and define it as partial.
for example, if you have a table called Files, the object File will be created for you by L2S. If you then create a file (with the same namespace as your DataContext object), and make it partial, like this:
public partial class File
{
}
You can just add properties, methods, etc. From within this class, you also have direct access to the properties of the 'other' File class.
It's a little klugy, but in your linq2sql designer, rename the field from 'id' to 'xid' (or anything else) and change its accessibility to internal.
then, in another file, start another partial class, like Wim Haanstra showed, and create a new property called 'id', add all the attributes you want, and in the get & set, just map it to and from the original property, now called 'xid'.
it would look something like this:
public partial class File
{
public int? id
{
get { return xid; }
set { xid = value; }
}
}
this is more commonly done to map fields in the database to a different type in the object, e.g. an int in the DB to an enum in the object, a byte/smallint/etc. in the DB, a boolean in the object. or to add attributes, like [DataMember] to the property.
Related
I am currently using Entity Framework for a project and one of my classes have an Enum representing some values.
So far EF is saving the Enums as numbers in the database, but I wanted to save them as their actual string names. For example, the Enum NY is saved as 1, instead of "NY".
I have already seen some ways to make this work, like having a string property with a hidden Enum private field, but I wanted to know if there is a way I can just Intercept EF when it's doing the CRUD operations and then I can change the Enum to a String in the Data Context class.
No, you cannot do that directly: when you map your class with an Enum property, that property is mapped to a database int column, and you cannot change that in any way. I mean that, as you cannot change the model, there is no way to intercept and convert the Enum property value into an string, because the model stubbornly wants an int.
That said, there are several ways to make it work:
having an string property for the key and a [NotMapped] Enum property that updates that key. SEE THE NOTE: But the key must be public, and thus accesible through the application code.
using a class that have only the enum property and is used in your application domain, and a different class which is used for your EF model, and map the values, for example using ValueInjecter or Automapper
I usually take the first path and use an attribute that allows me to define the string key for each Enum value, so you can reuse this pattern in all the cases in which need to do this.
NOTE: this part of the answer was wrong: you can map any property regardles of the modifier (public, protected, private, internal...). EF conventions only include the public properties, and there are no data annotations that can overcome this limitation. But you can use it with the Fluent API. However, as the property is private,you cannot access it directly using the Fluent API. There are several solutions to do it described here: Code First Data Annotations on non-public properties
If you follow this path, you can have a class like this:
public class MyEntity
{
// ...
[NotMapped]
public EnumType Value
{
get { /* return KeyForEnum converted to EnumType value */ }
set { /* set KeyForEnum value from the received EnumType value*/}
}
// Use some mechanism to map this private property
private string KeyForEnum { get; set; }
// ...
}
As you can see, if you use a class like this, in the app the entity will have a property of EnumType type, but in the database it will be an string.
One of the tricks to be able to map it through Fluent API is this:
1) Add an static property that returns an expression able to select the property from an object of this class, i.e.
public static readonly Expression<Func<MyEntity,string>> KeyForEnumExpression
= me => me.KeyForEnum;
2) Use it in the fluent API to get the property mapped, like so:
modelBuilder
.Entity()
.Property(MyEntity.KeyForEnumExpression)
LAST NOTE: This will modify the POCO class by adding the static readonly property. You can use Reflection instead to build an expression to access the private property, like you can see here: EF 4.1 Code First, ¿map private members?. It's in Spanish, but you can look directly at the code
In an old WPF project I have a class with Properties like this:
private string _name = "";
public string Name
{
get { return _name; }
set
{
string cleanName = clsStringManip.CleanText(value, true);
if (cleanName != _name)
{
_name = cleanName;
}
}
}
Where every time the name changes, I ensure that the value is "cleaned". Putting it in the property ensures I never forget to clean the string before setting the property on the object.
Now I am recreating this system using MVC5 and EntityFramework6.1 using DatabaseFirst.
So all the properties are autogenerated by EF. How then can I add the equivalent CleanText function to my properties without editing the autogen code? - as I'll lose these changes next time I change my database and resync.
All I can find via Google is a way add data annotations via MetadataType and partial classes but this doesn't answer my question.
I tried to add the above code into a partial class but get the error:
The type XXX already contains a definition for Name
The only way I can think is to create a bunch of SetProperty() functions but this is dirty and you can never ensure other developers (or myself) will remember to use them.
Disclaimer: I haven't used EF 6 yet.
Let me answer this in two parts. First, I will tell you how to do this. Then I will tell you why I don't think you should do this. :-)
HOW:
As you discovered, you cannot create another Name property. You need to modify the way the EF generates the code, so that it gives you a place to insert your new code. Depending on how you are using the EF, it often generates Validate() method calls or OnPropertyChanged() calls. You may be able to do what you want inside of those methods.
If you can't do this in Validate() or OnPropertyChanged(), you could change the T4 template to generate something like this:
private string _name = "";
public string Name
{
get { return _name; }
set
{
string cleanName = value;
Cleanup_Name(ref cleanName);
if (cleanName != _name)
{
_name = cleanName;
}
}
}
private partial void Cleanup_Name(ref string);
This gives you a partial method that you can then implement as you see fit. So for any property you want to customize, you can now add another file to your project that does this:
public partial class MyEntity {
void Cleanup_Name(ref string name)
{
// Put your logic in here to fixup the name
}
}
If you do not write the above code block, then the partial method is simply a no-op. (Partial methods must return void, hence the use of a ref parameter).
WHY NOT?
The advantage of this method is that it is totally transparent to the developer. The property is just magically changed. But there are several disadvantages:
Some controls expect that if they call name = "123" that if they get the name back, it is "123" and will fail if this happens. Values are changing but no PropertyChanged event fired. If you do fire the PropertyChanged, then they sometimes change the value back. This can cause infinite loops.
There is no feedback to the user. They typed in one thing, and it looked right, but now it says something different. Some controls might show the change and others won't.
There is no feedback to the developer. The watch window will seemingly change values. And it is not obvious where to see the validation rules.
The entity-framework itself uses these methods when it loads data from the database. So if the database already contains values that don't match the cleanup rules, it will clean them when loading from the database. This can make LINQ queries misbehave depending on what logic is run on the SQL server and what logic is run in the C# code. The SQL code will see one value, the C# will see another.
You might also want to look into what the Entity-Framework's change tracking does in this case. If a property set does a cleanup while loading values from the database, does it consider that a change to the entity? Will a .Save() call write it back to the database? Could this cause code that never intended to change the database to suddenly do so?
ALTERNATIVE
Instead of doing this, I suggest creating a Validate() method that looks at each property and returns errors indicating what is wrong. You could also even create a Cleanup() method that fixes the things that are wrong. This means the cleanups are no longer transparent, so the developer must call them explicitly. But that is a good thing: the code isn't changing values without them realizing it. The person writing the business logic or the UI knows at what point the values will change, and can get a list of why.
The only way you can achieve this is by creating a new property you actually use in your application. Perhaps you can hide the original property in the designer. The actual property you use could look like this:
public string ExternalName
{
get { return Name; }
set
{
string cleanName = clsStringManip.CleanText(value, true);
if (cleanName != Name)
{
Name = cleanName;
}
}
}
As an alternative, you can use POCO classes:
If you want to keep using database-first, check this answer
Use code-first for an existing database, see this detailed guide
Add partial to the generated class.
Change the scope of Name in the generated class from public to internal.
Add the following in the same assembly:
public partial class classname
{
[NotMapped]
public string CleanName
{
get { return Name; }
set
{
var cleanName = clsStringManip.CleanText(value, true);
if (cleanName != Name)
Name = cleanName;
}
}
}
Caveat: you'd have to remember to do steps 1-2 every time you regenerated your POCOs ... I'd seriously consider Code First to Existing Database.
EDIT
Optionally:
Rename Name as InternalName in the generated classname; decorate it with [Column("Name")].
Rename CleanName as Name in the partial class under your control.
Caveat in 4 becomes "remember to do steps 1, 2, and 5 every time you regenerate POCOs".
This approach has the added benefit of not having to modify any of your client code (i.e., use of Name remains Name). And I'd still strongly consider Code First to Existing Database.
UserAccount objUserAccount=null;
AutoMapper.Mapper.CreateMap<AccountBO, UserAccount>();
objUserAccount = AutoMapper.Mapper.Map<AccountBO, UserAccount>(lstAcc[0]);
Up to this point it is mapping AccountBO properties fine.
Now I have to map object objAddressBO properties to destination including above mapped values. for this I have written code as below following to above lines of code.
AutoMapper.Mapper.CreateMap<AddressBO,UserAccount>();
objUserAccount=AutoMapper.Mapper.Map<AddressBO,UserAccount>(objAddressBO);
But it's losing first time mapped values and returning only the last time mapped values.
Please let me know what changes I need to do to have both the values in my destination object.
You should only configure the mapping once. The best way to do this is by using profiles:
public class MyProfile : Profile
{
public override string ProfileName
{
get
{
return "MyProfile";
}
}
protected override void Configure()
{
AutoMapper.Mapper.CreateMap<AccountBO, UserAccount>();
AutoMapper.Mapper.CreateMap<AddressBO,UserAccount>();
}
}
This should then be initialised in an initialisation method (such as App_Start for web projects)
You should also create a unit test to test the mapping has been configured correctly
[TestFixture]
public class MappingTests
{
[Test]
public void AutoMapper_Configuration_IsValid()
{
Mapper.Initialize(m => m.AddProfile<MyProfile>());
Mapper.AssertConfigurationIsValid();
}
}
If that all works fine, and assuming I have understood the question correctly, you want to initialise objUserAccount from listAcc[0], then fill in some additional parameters from objAddressBO. You can do this like:
objUserAccount = Mapper.Map<AccountBO, UserAccount>(lstAcc[0]);
objUserAccount= Mapper.Map(objAddressBO, objUserAccount);
The first map will create the object, and the second map will update the provided destination object.
Note that for this to work correctly you may need to fill out your mapping configuration a little to provide the correct behaviour. For example, if you wish to avoid updating a destination property you can use the UseDestinationValue directive. If you want to apply a condition to the update you can use the Condition directive. If you wish to ignore the property completely, you can use the Ignore directive.
If required, more documentation can be found here.
I'm trying to insert properties dynamically to a class.
I need to load properties from database and show it in PropertyGrid, but I want to it to be build in run time, it means that I want to insert property definition to database and to load it to a class(My Class) in runtime.
e.g - if the data base contains row that define property (e.g Name of type string)
the class should something like this:
public MyClass
{
public string Name{get; set;}
}
I also tried to do it using dynamic but it failed.
any ideas?
Thank you.
You can use an ExpandoObject.
I would use Simple.Data to do this. It fetches data from the database and constructs dynamic objects from the query :)
I am a beginner when it comes to databases and c# (using them together) and I am trying to associate the values from a database to the attributes of a class.
I remember seing somewhere something like:
private attribute
[Data binding]
public Attribute
{
get { return attribute; }
set { attribute = value; }
}
What is it? What should I look to use something like this. I am using an ADO.NET EMD, but I'm not sure what to do next mainly because I am not sure what to look into.
You're probably thinking of the [Bindable] attribute that can be placed on properties of a Control to tell Visual Studio to show the property in the DataBindings node in the designer.
It's expected that you'll wire up that attribute to something in your UserControl, like a textbox.