PetaPoco and Ignore attribute - c#

I have the following class:
public class Foo
{
public int Id { get; set; }
...
public Boo Boo1 { get; set; }
public Boo Boo2 { get; set; }
}
I want to exclude Boo1 and Boo2 properties but I don't want to decorate those properties with PetaPoco.Ignore attribute. I want to have pure POCO objects. Can I execute Ignore command in code or do I have to create query/stored procedure and manually map all fields?
Any help would be greatly appreciated!

Looks like PetaPoco can't be told in any other way that fields/properties should be ignored than by using attributes. You can either Ignore a few members, or if you're not mapping the majority of a class then you can specify explicit column mapping for the class and decorate the ones you DO want mapped. I understand your hesitance to add ORM-specific cruft to a "pure" POCO, but unfortunately that information has to be somewhere, and as PetaPoco doesn't use mapping files (or much of a configuration at all, really), the class is where it goes.
The only thing you could do is create a DTO/DAO that will be what is mapped, then create implicit or explicit operators to convert between the domain class and its DTO. The DTO, then, can simply not have the fields you don't want to include. That keeps both classes POCO (depending on your feelings regarding operator methods), and it just adds a relatively simple step of casting the query result to your domain class.

In my branch here:
https://github.com/schotime/PetaPoco
You can fluently describe your models like I have described here: http://schotime.net/blog/index.php/2011/05/16/fluent-petapoco-external-mappings/ and also use the convention based mapping like here: http://schotime.net/blog/index.php/2012/02/13/petapoco-convention-based-fluent-mapping/

This is a great place for an anonymous type.
In your method for saving foo
public void InsertFoo(Foo f)
{
var db = new Database("connection");
var petaPocoFooObj = new {f.Id}
db.Insert("FooTable", "FooId", petaPocoFooObj);
}
It's just a little more work, although it could be a PITA if your classes are deeply nested.

Related

How can I change properties' names (of auto generated classes) in serialization?

I have a class like below, auto generated by Entity Framework, based in our database:
public partial class TB_Cliente
{
public int IDCliente { get; set; }
public string Nome { get; set; }
// other properties
}
I'm using DataContractJsonSerializer and I need to change the properties' names in serialization. For instance, the property IDCliente must be serialized like ClientID.
I can't use [DataMember] in top of the property, because the class is auto generated, and any future changes will generate the class again and these changes will be lost.
I've had the same problem in the past, when I wanted to use data annotations. I've found the below solution, creating another file and using an interface, which works perfectly:
public interface ITB_Cliente
{
[Required]
string Nome { get; set; }
// other properties
}
[MetadataType(typeof(ITB_Cliente))]
public partial class TB_Cliente : ITB_Cliente
{
}
But this solution doesn't help me now, because (as far as I know) this attribute must be set directly in the class. I've tried to set it in the interface and it didn't work.
Is there a way to change the properties' names in the serialization, in my case? Any help will be greatly appreciated.
You probably want to use DTOs for serialization. I have not tried but AutoMapper can probably do the heavy lifting for you.
I have been trying to overcome a similar problem this week for JSON output from some legacy VB.Net classes that I would prefer not to change if I can avoid it. The serialisation is returning underlying private member names rather than the public property names, e.g. "mFirstName".
Also for autogenerated property names I am getting json like
{"k__BackingField":"Brian","k__BackingField":"Furlong"}
which is not good.
I considered a similar approach to Pawel's above (create DTOs and use Automapper which I have used extensively before).
I am also checking to see if I can make a customised json serialiser but haven't got very far yet.
The third way I have investigated is to create an "Aspect" using PostSharp which will decorate the business entity classes with the DataContract.
This would allow me to create the necessary [DataContract] and [DataMember] attributes on the public properties at compile time without having to modify the legacy code base. As I am using the legacy assemblies within a new WebAPI assembly it effectively extends the code for me.
For guidance / hints please refer to the following links:
For background information http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer
For the question that gave the pointer: How to inject an attribute using a PostSharp attribute?
For a walkthrough on how to do something similar which is enough to get going on this: http://www.postsharp.net/blog/post/PostSharp-Principals-Day-12-e28093-Aspect-Providers-e28093-Part-1

Make EF convert properties of a castable-to-string-type to string before sending to the database

Is there a way I can tell EF to convert my MultilingualString properties to string before sending them to the database (and the other way around when fetching from database) ? I want to wrap the behaviour to reuse it.
public class MyEntity
{
// I want this property to be considered a string by EF (it is castable to string)
public MultilingualString MyProperty { get; set; }
}
public class MultilingualString
{
public static implicit operator string(MultilingualString mlString)
{
return mlString.ToJson();
}
public static explicit operator MultilingualString(string json)
{
return new MultilingualString(json);
}
...
}
Three thoughts:
One is to to generate your classes from a T4 template that will generate the backing field and the [NotMapped] MultilingualString. Technically you'll be writing less code, and each T4 template could use a method you put in from another assembly to keep from repeating the generation code in each template. I do acknowledge that this idea isn't going to make you feel better, though.
Thought two is to use PostSharp, attribute up your backing fields and have a PostSharp extension create the multilingual fields, or vice versa. The large downside to this is that static analysis tools are not going to like it much.
Thought three is to make MultilingualString a ComplexType that contains the string field as a public property and also has whatever other methods you have built the class to perform at the moment. It will generate a more messy database column name, if you care about that.
I reckon 3 has the most value.
EDIT:
For option 3 you can control the column names if you need to:
modelBuilder.Entity<MyEntity>().Property(x => x.MyProperty.StringValue)
.HasColumnName("i_dba_aprvd_rdbl_col_nm")
There's no reason this fluent configuration couldn't be generated using reflection to find all such complex property values if there was a rule by which the column name could be determined, e.g. it was the name of the property of type MultilingualString on the entity.

Automapping custom types

I am in the process of setting up nhibernate using fluent nhibernate for a relatively simple setup. Automapping is able to do everything currently fine except for one property on my objects.
I have properties of type MongoDB.Bson.ObjectId. This is simple immutable struct that basically represents a binary ID that can be easily represented in string format as well. These properties cause NHibernate to throw an error saying:
An association from the table PostView refers to an unmapped class:
MongoDB.Bson.ObjectId
This is quite expected of course because I don't expect nhibernate to understand what ObjectId is.
Where I am stuck is that what I want is to be able to tell Nhibernate to map this object type to a string representation in the database. I would like to be able to do this while still using automapping so I don't have to explicitly map all of those objects - what I'd like is to be able to just say "Whenever you find this objecttype use this mapping". I've found mention of NHibernate.UserTypes.IUserType which seems to look like it does what I want but I've found nothing that usefully tells me how to use it.
So to summarise the question:
How can I automatically map a custom data type to a known type for storing in the database (and of course the reverse).
I would prefer not to change my objects to storing the string representation of the object if possible.
You have to write a convention for this type.
Something like this:
public class CustomTypeConvention : IUserTypeConvention
{
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType == typeof(MyType));
}
public void Apply(IPropertyInstance target)
{
target.CustomType(typeof(string));
}
}
And add this convention to mappings:
mapping.Conventions.Add(new CustomTypeConvention());

How do attribute classes work?

My searches keep turning up only guides explaining how to use and apply attributes to a class. I want to learn how to create my own attribute classes and the mechanics of how they work.
How are attribute classes instantiated? Are they instantiated when the class they are applied to is instantiated? Is one instantiated for each class instantiated that it is applied to? E.g. if I apply the SerializableAttribute class to a MyData class, and I instantiate 5 MyData instances, will there be 5 instances of the SerializbleAttribute class created behind the scenes? Or is there just one instance shared between all of them?
How do attribute class instances access the class they are associated with? How does a SerializableAttribute class access the class it is applied to so that it can serialize it's data? Does it have some sort of SerializableAttribute.ThisIsTheInstanceIAmAppliedTo property? :) Or does it work in the reverse direction that whenever I serialize something, the Serialize function I pass the MyClass instance to will reflectively go through the Attributes and find the SerialiableAttribute instance?
I haven't use attributes in my day-to-day work before, but I have read about them.
Also I have done some tests, to back up what I'll say here. If I'm wrong in any place - feel free to tell me this :)
From what I know, attributes are not acting as regular classes. They aren't instantiated when you create an object that they are applied to, not one static instance, not 1 per each instance of the object.
Neither do they access the class that they are applied to..
Instead they act like properties (attributes? :P ) of the class. Not like the .NET class properties, more like in the "one property of glass is transparency" kind of property. You can check which attributes are applied to a class from reflection, and then act on it accordingly. They are essentially metadata that is attached to the class definition, not the objects of that type.
You can try to get the list of attributes on a class, method, property, etc etc.. When you get the list of these attributes - this is where they will be instantiated. Then you can act on the data within these attributes.
E.g. the Linq tables, properties have attributes on them that define which table/column they refer to. But these classes don't use these attributes. Instead, the DataContext will check the attributes of these objects when it will convert linq expression trees to SQL code.
Now for some real examples.. I've ran these in LinqPad, so don't worry about the strange Dump() method. I've replaced it with Console.WriteLine to make the code easier to understand for the people who don't know about it :)
void Main()
{
Console.WriteLine("before class constructor");
var test = new TestClass();
Console.WriteLine("after class constructor");
var attrs = Attribute.GetCustomAttributes(test.GetType()).Dump();
foreach(var attr in attrs)
if (attr is TestClassAttribute)
Console.WriteLine(attr.ToString());
}
public class TestClassAttribute : Attribute
{
public TestClassAttribute()
{
DefaultDescription = "hello";
Console.WriteLine("I am here. I'm the attribute constructor!");
}
public String CustomDescription {get;set;}
public String DefaultDescription{get;set;}
public override String ToString()
{
return String.Format("Custom: {0}; Default: {1}", CustomDescription, DefaultDescription);
}
}
[Serializable]
[TestClass(CustomDescription="custm")]
public class TestClass
{
public int Foo {get;set;}
}
The console result of this method is:
before class constructor
after class constructor
I am here. I'm the attribute constructor!
Custom: custm; Default: hello
And the Attribute.GetCustomAttributes(test.GetType()) returns this array:
(the table shows all available columns for all entries.. So no, the Serializable attribute does not have these properties :) )
Got any more questions? Feel free to ask!
UPD:
I've seen you ask a question: why use them?
As an example I'll tell you about the XML-RPC.NET library.
You create your XML-RPC service class, with methods that will represent the xml-rpc methods. The main thing right now is: in XmlRpc the method names can have some special characters, like dots. So, you can have a flexlabs.ProcessTask() xml rpc method.
You would define this class as follows:
[XmlRpcMethod("flexlabs.ProcessTask")]
public int ProcessTask_MyCustomName_BecauseILikeIt();
This allows me to name the method in the way I like it, while still using the public name as it has to be.
Attributes are essentially meta data that can be attached to various pieces of your code. This meta data can then be interogate and affect the behaviour of certain opperations.
Attributes can be applied to almost every aspect of your code. For example, attributes can be associated at the Assembly level, like the AssemblyVersion and AssemblyFileVersion attributes, which govern the version numbers associated with the assembly.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Then the Serializable attribute for example can be applied to a type declaration to flag the type as supporting serialization. In fact this attribute has special meaning within the CLR and is actually stored as a special directive directly on the type in the IL, this is optimized to be stored as a bit flag which can be processed much more efficiently, there are a few attributes on this nature, which are known as pseudo custom attributes.
Still other attributes can be applied to methods, properties, fields, enums, return values etc. You can get an idea of the possible targets an attribute can be applied to by looking at this link
http://msdn.microsoft.com/en-us/library/system.attributetargets(VS.90).aspx
Further to this, you can define your own custom attributes which can then be applied to the applicable targets that your attributes are intended for. Then at runtime your code could reflect on the values contained in the custom attributes and take appropriate actions.
For a rather naive example, and this is just for the sake of example :)
You might want to write a persistence engine that will automatically map Classes to tables in your database and map the properties of the Class to table columns. You could start with defining two custom attributes
TableMappingAttribute
ColumnMappingAttribute
Which you can then apply to your classes, as an example we have a Person class
[TableMapping("People")]
public class Person
{
[ColumnMapping("fname")]
public string FirstName {get; set;}
[ColumnMapping("lname")]
public string LastName {get; set;}
}
When this compiles, other than the fact that the compiler emits the additional meta data defined by the custom attributes, little else is impacted. However you can now write a PersistanceManager that can dynamically inspect the attributes of an instance of the Person class and insert the data into the People table, mapping the data in the FirstName property to the fname column and the LastName property to the lname column.
As to your question regarding the instances of the attributes, the instance of the attribute is not created for each instance of your Class. All instances of People will share the same instance of the TableMappingAttribute and ColumnMappingAttributes. In fact, the attribute instances are only created when you actually query for the attributes the first time.
Yes they're instantiated with the parameters you give it.
The attribute does not "access" the class. The attribute is attached to the class' / property's attribute list in the reflection data.
[Serializable]
public class MyFancyClass
{ ... }
// Somewhere Else:
public void function()
{
Type t = typeof(MyFancyClass);
var attributes = t.GetCustomAttributes(true);
if (attributes.Count(p => p is SerializableAttribute) > 0)
{
// This class is serializable, let's do something with it!
}
}
Think of attributes are post-its that are attached to the classes or method definitions (embedded in the assembly metadata).
You can then have a processor/runner/inspector module that accepts these types by reflecting, looks for these post-its and handles them differently. This is called declarative programming. You declare some behavior instead of writing code for them in the type.
Serializable attribute on a type declares that it is built to be serialized. The XmlSerializer can then accept an object of this class and do the needful. You mark the methods that need to be serialized/hidden with the right post-its.
another example would the NUnit. The NUnit runner looks at the [TestFixture] attributes all classes defined in the target assembly to identify test classes. It then looks for methods marked with [Test] attribute to identify the tests, which it then runs and displays the results.
You may want to run through this tutorial at MSDN which has most of your questions answered along with an example at the end. Although they could have extracted a method called
Audit(Type anyType); instead of duplicating that code. The example 'prints information' by inspecting attributes.. but you could do anything in the same vein.
If you take an eye out this downloadable open source code LINQ to Active Directory (CodePlex), you might find interesting the mechanism of the Attributes.cs file where Bart De Smet has written all of his attributes classes definitions. I have learned attributes there.
In short, you may specialize the Attribute class and code some specialized properties for your needs.
public class MyOwnAttributeClass : Attribute {
public MyOwnAttributeClass() {
}
public MyOwnAttributeClass(string myName) {
MyName = myName;
}
public string MyName { get; set; }
}
and then, you may use it wherever MyOwnAttributeClass gets useful. It might either be over a class definition or a property definition.
[MyOwnAttributeClass("MyCustomerName")]
public class Customer {
[MyOwnAttributeClass("MyCustomerNameProperty")]
public string CustomerName { get; set; }
}
Then, you can get it through reflection like so:
Attribute[] attributes = typeof(Customer).GetCustomAttribute(typeof(MyOwnAttributeClass));
Consider that the attribute you put between square brackets is always the constructor of your attribute. So, if you want to have a parameterized attribute, you need to code your constructor as such.
This code is provided as is, and may not compile. Its purpose is to give you an idea on how it works.
Indeed, you generally want to have a different attribute class for a class than for a property.
Hope this helps!
Not much time to give you a fuller answer, but you can find the Attributes that have been applied to a value using Reflection. As for creating them, you inherit from the Attribute Class and work from there - and the values that you supply with an attribute are passed to the Attribute class's constructor.
It's been a while, as you might be able to tell...
Martin

Programming to interfaces while mapping with Fluent NHibernate

I have been whipped into submission and have started learning Fluent NHibernate (no previous NHibernate experience). In my project, I am programming to interfaces to reduce coupling etc. That means pretty much "everything" refers to the interface instead of the concrete type (IMessage instead of Message). The thought behind this is to help make it more testable by being able to mock dependencies.
However, (Fluent) NHibernate doesn't love it when I try to map to interfaces instead of concrete classes. The issue is simple - according to the Fluent Wiki, it is smart to define the ID field of my class as for instance
int Id { get; private set; }
to get a typical auto-generated primary key. However, that only works with concrete classes - I can't specify an access level on an interface, where the same line has to be
int Id { get; set; }
and I guess that negates making the setter private in the concrete class (the idea being that only NHibernate should ever set the ID as assigned by the DB).
For now, I guess I will just make the setter public and try to avoid the temptation of writing to it.. But does anyone have an idea of what would be the "proper", best-practice way to create a proper primary-key field that only NHibernate can write to while still only programming to interfaces?
UPDATED
From what I understand after the two answers below from mookid and James Gregory, I may well be on the wrong track - there shouldn't be a reason for me to have an interface per entity as I have now. That's all well and good. I guess my question then becomes - is there no reason to program 100% against an interface for any entities? And if there is even a single situation where this could be justified, is it possible to do this with (Fluent) NHibernate?
I ask because I don't know, not to be critical. Thanks for the responses. :)
I realise this is a diversion, and not an answer to your question (although I think mookid has got that covered).
You should really evaluate whether interfaces on your domain entities are actually providing anything of worth; it's rare to find a situation where you actually need to do this.
For example: How is relying on IMessage any less coupled than relying on Message, when they both (almost) undoubtedly share identical signatures? You shouldn't need to mock an entity, because it's rare that it has enough behavior to require being mocked.
You can adjust your interface to contain only a getter:
public interface ISomeEntity
{
int Id { get; }
}
Your concrete class can still implement a setter as well, and since you are programming to your interfaces you will never call the setter "by accident".
If you want to disallow setting the id even when you hold a reference to a concrete instance, you can refrain from implementing a setter, and then let NHibernate access the field instead of the property - that's right, NHibernate can use some nifty reflection trickery to set your id field directly instead of invoking the property. Then you might map the id like this:
Id(e => e.Id).Access.AsCamelCaseField();
in which case your Id property must be backed by a corresponding id field. There are more naming conventions, e.g. if you prefer underscores as private field prefix.
I am having exactly the same issue.
Unfortunately I have a valid reason for using entity interfaces; the entity model will be implemented in different ways and with different mappings per customer.
The entire model needs to be read-only, so interfaces are of the style:
public interface IAccount
{
long AccountId { get; }
IHouse House { get; }
}
public interface IHouse
{
long HouseId { get; }
HouseStatus Status { get; }
IList<IAccount> Accounts { get; }
}
Concrete implementations then implement these with internal setters:
public class Account: IAccount
{
public virtual long AccountId { get; internal set; }
public virtual IHouse House { get; internal set; }
}
public class House: IHouse
{
public virtual long HouseId { get; internal set; }
public virtual HouseStatus Status { get; internal set; }
public virtual IList<IAccount> Accounts { get; internal set; }
}
I have gone down the route of mapping to the concrete classes. All is fine until you create relations which return interfaces and need to be cast to concrete implementations.
HasMany(x => x.Accounts)
can become
HasMany<Account>(x => x.Accounts)
But there is no equivalent 'cast' for
References(x => x.House)
Mapping to the interfaces (the neater solution) throws up the problem mentioned above in that the Id must exist on the topmost class for setting and requires a setter on the interface.
public sealed class AccountMap : ClassMap<IAccount>
{
public PokerPlayerMap()
{
Id(x => x.AccountId, "account_id");
DiscriminateSubClassesOnColumn("Type").SubClass<Account>(s =>
{
References(x => x.House);
});
}
}
For now, my only solution is to add setters to all of the interface Id fields. Its a shame the Id can't exist inside a subclass or have its type cast from the interface.
UPDATE: using union-subclass is not supported via the fluent interface fluent-nhibernate provides. You'll have to use a regular hbm mapping file and add it.
I too I'm trying do this with fluent NHibernate. I don't think it should be a problem mapping interfaces. You want to use an inheritance strategy, specifically the table-per-concrete-class strategy.
Essentially, you create a mapping definition for the base class (in this case your interface) and specify how to NHibernate should deal with implementers by using union-subclass.
So, for example, this should allow you to make polymorphic associations:
<class name="IAccountManager"
abstract="true"
table="IAccountManager">
<id name="Id">
<generator class="hilo"/>
</id>
<union-subclass
table="DefaultAccountManager"
name="DefaultAccountManager">
<property name="FirstName"/>
</union-subclass>
<union-subclass
table="AnotherAccountManagerImplementation"
name="AnotherAccountManagerImplementation">
<property name="FirstName"/>
</union-subclass>
...
</class>
Note how the Id is the same for all concrete implementers. NHibernate required this. Also, IAccountManager table doesn't actually exist.
You can also try and leverage NHibernate's Implicit Polymorphism (documented below the table-per-concrete-class strategy) - but it has tons of limitations.
Looks like I don't have enough reputation to comment on other peoples answers yet as such I'm going to have to make this an answer in it's own right.
References now has a generic overload to allow the cast that theGecko was looking for in his answer.

Categories

Resources