Entity Framework: read only property vs parameter-less method - c#

Consider following class
public class AccountGroup : Entity<int>
{
public AccountGroup()
{
Accounts = new HashSet<Account>();
Groups = new HashSet<AccountGroup>();
}
// option 1 - read only properties
public bool IsRoot { get { return Parent == null; } }
public bool IsLeaf { get { return !Groups.Any(); } }
public Account MainAccount { get { return Accounts.FirstOrDefault(a=>a.Type == AccountType.MainAccount); } }
// option 2 - parameter-less methods
//public bool IsRoot() { return Parent == null; }
//public bool IsLeaf() { return !Groups.Any(); }
//public Account GetMainAccount() { return Accounts.FirstOrDefault(a => a.Type == AccountType.MainAccount); }
public string Name { get; set; }
public string Description { get; set; }
public virtual ISet<Account> Accounts { get; private set; }
public virtual ISet<AccountGroup> Groups { get; private set; }
public virtual AccountGroup Parent { get; set; }
}
If I want to "enrich" the class above, which option approach should I use.
Option 1
Should I use read only parameters knowing that EF does not like them (trying to use IsRoot in Where clause throws ex, with The specified type member 'IsRoot' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Option 2
Or should I go with parameter-less methods (not sure what would be disadvantages)
In general (not considering EF), which approach is preferred considering above when functionality is equivalent (i.e. I get the same functionality if I invoke .IsRoot or .IsRoot())

IsRoot feels more like a property to me. It represents current state of the object, doesn't actually do anything when invoked other than report that state, and generally getters/setters in .NET are properties.
There are other things to consider, a JSON/XML serializer will not serialize IsRoot() but will for IsRoot as a property. Generally speaking a lot of things in .NET hinge off of properties, so often they are the better choice.
EF wouldn't like IsRoot() either, it just doesn't know how to translate IsRoot into SQL, whether it's a property or method.

In general (as you say, not taking limitations of EF into account), the approach for domain models in this particular context would probably be a read-only property.
Consider that the property is simply checking state, not modifying it in any way. A read-only property conveys, outside of the object, that it's just returning a piece of information. On the other hand, a method could be potentially destructive in that it might modify information.
This would be particularly true if the method returned void of course, which isn't the case here, so this could be considered a borderline issue (and not even a question in languages which don't have "properties" but just use accessor methods, which under the hood is what a "property" does).
My vote is for a property when checking state and a method when commanding the object to modify state.

Have you already tried decorating IsRoot with [NotMapped]? The NotMapped attribute should prevent Entity Framework from complaining about properties that it's unable to persist and allow you to express that as a property.

Related

Exception when querying with an explicit Interface using MongoDB C# driver

I need to construct a query using as a FilterDefinition an explicit Interface but it throws an exception saying :
System.InvalidOperationException
Message={document}.Pointer is not supported.
Source=MongoDB.Driver
I have tried this with normal Interface implementation and it works as expected.
But I need to implement an Interface explicitly as I'm having 2 interfaces with the same property names as shown in the code below:
public class Offer : OfferBase, IPointerTo<ServiceCategory>,
IPointerTo<Company>
{
[BsonElement("_p_ServiceCategoryObj")]
[JsonProperty("serviceCategoryObj")]
string IPointerTo<ServiceCategory>.Pointer { get; set; }
[BsonElement("_p_companyObj")]
[JsonProperty("companyObj")]
string IPointerTo<Company>.Pointer { get; set; }
}
So, I create a FilterDefinition that I will use in a Find.
As I mentioned before, this works fine if it were not an explicit interface implementation. For instance: if just use one of them normally implemented and the other explicitly it will work when querying for the normal one. But having the above code constraints and creating the filter like this:
FilterDefinition<Offer> innnerFilter = MongoQueryBuilder.AddFilter<Offer>
(offer =>string.IsNullOrEmpty((offer as
IPointerTo<ServiceCategory>).Pointer));
So when the Find with that filter is being executed the exception stated above is being thrown.
Note: MongoQueryBuilder.AddFilter is just a wrapper that I did to make it easier but that it's not the issue as all the other queries work fine using that.
I would expect to get the results as I get them when just having one of the interfaces implemented normally and querying with that Interface member but in my current scenario I need to have them both implemented and thus they must be implemented explicitly.
I may not be doing something properly or using it as I should but I haven't been to find any solution to this.
Edit: (thanks to #Lakerfield answer)
I was not able to find Pointer as I was asking for Offer and as Pointer it's an explicit interface it was not being able to publicly find it.
So, I was able to solve it like this:
public class Offer : OfferBase, IPointerTo<ServiceCategory>, IPointerTo<Company>
{
[BsonIgnoreIfNull]
[BsonIgnoreIfDefault]
[BsonElement("_p_ServiceCategoryObj")]
[JsonProperty("serviceCategoryObj")]
public string ServiceCategoryPointer
{
get => (this as IPointerTo<ServiceCategory>).Pointer;
set => (this as IPointerTo<ServiceCategory>).Pointer = value;
}
[BsonIgnore]
string IPointerTo<ServiceCategory>.Pointer { get; set; }
[BsonIgnoreIfNull]
[BsonIgnoreIfDefault]
[BsonElement("_p_companyObj")]
[JsonProperty("companyObj")]
public string CompanyPointer
{
get => (this as IPointerTo<Company>).Pointer;
set => (this as IPointerTo<Company>).Pointer = value;
}
[BsonIgnore]
string IPointerTo<Company>.Pointer { get; set; }
And then doing the query like this: (Now I'm use Linq instead of FilterDefinition but that is not relevant for the sake of this solution)
private static Expression<Func<Offer, bool>> InnerQueryServiceCategory(string serviceCategoryId)
{
return offer => (offer.IsDeleted == false || !offer.IsDeleted.HasValue) && offer.ServiceCategoryPointer == PointedCollections.ServiceCategoryCollection.GetDescription() + serviceCategoryId;
}
offer.ServiceCategoryPointer is publicly available and it's a member of Offer.
The problem is the duplicate Pointer property name. In MongoDB a object must have unique propertynames.
Workaround just use two seperate properties with different names, forward your explicit interfaces to those, and use the new properties in your query.
public class Offer : OfferBase, IPointerTo<ServiceCategory>, IPointerTo<Company>
{
public string ServiceCategoryPointer { get; set; }
public string CompanyPointer { get; set; }
string IPointerTo<ServiceCategory>.Pointer
{
get => ServiceCategoryPointer;
set => ServiceCategoryPointer = value;
}
string IPointerTo<Company>.Pointer
{
get => CompanyPointer;
set => CompanyPointer = value;
}
}

Why use private variables with properties - Code first

A introduce
If you make all your properties virtual then EF will generate proxy classes at runtime that derives from your POCO classed, these proxies allow EF to find out about changes in real time rather than having to capture the original values of your object and then scan for changes when you save (this is obviously has performance and memory usage benefits but the difference will be negligible unless you have a large number of entities loaded into memory). These are known as 'change tracking proxies', if you make your navigation properties virtual then a proxy is still generated but it is much simpler and just includes some logic to perform lazy loading when you access a navigation property.
Reference: http://social.msdn.microsoft.com/Forums/en/adonetefx/thread/99d8d4a1-5ab1-42dc-b9db-5087be02162d
[1]
public virtual ICollection<Log> Logs { get; set; }
[2]
private ICollection<Log> _logs;
public virtual ICollection<Log> Logs
{
get
{
if(_logs == null) Logs = new HashSet<Log>();
return Logs ;
}
private set {}
}
[3]
private ICollection<Log> _logs;
public virtual ICollection<Log> Logs
{
get
{
if(_logs == null) _logs = new HashSet<Log>();
return _logs;
}
set {_logs = value; }
}
How is better thinking in EF - Code first?
Why some people use private fields with properties?
private set can be help to avoid modify the full list
In [1] we can have null references, forcing verify if is null before use the property
But, private variables/fields, I not understand why is necessary. I think propertys in "backend" generate private fields, so?
Like you said, in [1] you can have a null reference exception (usually when you create a new parent class and then you add a new Log.
An approach to avoid it is to:
- write [2]
- initialize it in the parent class constructor
- with c# 5 you can write
public virtual ICollection<Log> Logs { get; set; } = new new HashSet<Log>();
The [3] is not usefull (if you initialize Logs property, EF do not need to access to setter).
Another interesting thing is that you can use your own collection i.e.
public class LogCollection : ObservableCollection<Log>
{
public Post Add(string content)
{
Log log = new Log
{
Date = DateTime.Now,
Content = content
};
Add(log);
return log;
}
}
and then use it in the master class instead of ICollection, i.e.
public virtual LogCollection Logs
{
get
{
if(_logs == null) Logs = new HashSet<Log>();
return Logs ;
};
private set;
}
Usually I initialize collections in class constructor, I don't use backing field and my setter is public (but probably I never used it outside the parent class so it's a stupid way to implement it). But it's my way of work with c# 4.x
EDIT
About a part of your question, EF does not use backing fields, it access only to property setter and getter. You can force to use private backing fields (map backing fields) mapping it via fluent interface and mapping it in an inner class.

Map from a Char to a Boolean

We are using Dapper as an ORM to a legacy Informix database, and within this database boolean fields are actually stored as a Char, with 'F' meaning False and 'T' meaning True.
Within our POCO, we would like to expose a single boolean property and instruct Dapper to map to/from the relevant char value when reading from and writing to the database.
For Example:
Let's say we have a field within a table called "Active". The value in the database for the Active column will be either "T" of "F"
Our POCO may look something like this:
public class MyTable
{
public bool Active { get; set; }
}
Is it possible to create a custom mapping within Dapper that for this column would set the Active property in the POCO to true if the underlying value is "T", and false if "F"?
One way I know I could work around this is to have two properties, one a string that Dapper can map to directly and another a boolean used by the consumers of the POCO. i.e:
public class MyTable
{
public string Active { get; set; }
public bool MyActive
{
get { return Active == "T"; }
set { Active = (value == "T"); }
}
}
The disadvantage of this approach is having to maintain two properties so it would be a great if there is a way to extend dapper to get it to do this for me (particularly as there are a lot of fields like this within the table our database).
I've looked at implementing a custom type map but although this would work for a custom complex type, I'm not sure how it would work in this instance when I want to map from one basic type to a another basic type.
I doubt that dapper supports it, have a look at this related question's answer. As you can see the Active-property does not even have to be public, make it private to avoid confusion. However, i would name your bool property IsActive.
public class MyTable
{
private string Active { get; set; }
public bool IsActive
{
get { return Active == "T"; }
set { Active = value ? "T" : "F"; }
}
}

`Type.GetProperties` property order

Short Version
The MSDN documentation for Type.GetProperties states that the collection it returns is not guaranteed to be in alphabetical or declaration order, though running a simple test shows that in general it is returned in declaration order. Are there specific scenarios that you know of where this is not the case? Beyond that, what is the suggested alternative?
Detailed Version
I realize the MSDN documentation for Type.GetProperties states:
The GetProperties method does not return properties in a particular
order, such as alphabetical or declaration order. Your code must not
depend on the order in which properties are returned, because that
order varies.
so there is no guarantee that the collection returned by the method will be ordered any specific way. Based on some tests, I've found to the contrary that the properties returned appear in the order they're defined in the type.
Example:
class Simple
{
public int FieldB { get; set; }
public string FieldA { get; set; }
public byte FieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple Properties:");
foreach (var propInfo in typeof(Simple).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Simple Properties:
FieldB
FieldA
FieldC
One such case that this differs only slightly is when the type in question has a parent who also has properties:
class Parent
{
public int ParentFieldB { get; set; }
public string ParentFieldA { get; set; }
public byte ParentFieldC { get; set; }
}
class Child : Parent
{
public int ChildFieldB { get; set; }
public string ChildFieldA { get; set; }
public byte ChildFieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parent Properties:");
foreach (var propInfo in typeof(Parent).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
Console.WriteLine("Child Properties:");
foreach (var propInfo in typeof(Child).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}
Output:
Parent Properties:
ParentFieldB
ParentFieldA
ParentFieldC
Child Properties:
ChildFieldB
ChildFieldA
ChildFieldC
ParentFieldB
ParentFieldA
ParentFieldC
Which means the GetProperties method walks up the inheritance chain from bottom up when discovering the properties. That's fine and can be handled as such.
Questions:
Are there specific situations where the described behavior would differ that I've missed?
If depending on the order is not recommended then what is the recommended approach?
One seemingly obvious solution would be to define a custom attribute which indicates the order in which the properties should appear (Similar to the Order property on the DataMember attribute). Something like:
public class PropOrderAttribute : Attribute
{
public int SeqNbr { get; set; }
}
And then implement such as:
class Simple
{
[PropOrder(SeqNbr = 0)]
public int FieldB { get; set; }
[PropOrder(SeqNbr = 1)]
public string FieldA { get; set; }
[PropOrder(SeqNbr = 2)]
public byte FieldC { get; set; }
}
But as many have found, this becomes a serious maintenance problem if your type has 100 properties and you need to add one between the first 2.
UPDATE
The examples shown here are simply for demonstrative purposes. In my specific scenario, I define a message format using a class, then iterate through the properties of the class and grab their attributes to see how a specific field in the message should be demarshaled. The order of the fields in the message is significant so the order of the properties in my class needs to be significant.
It works currently by just iterating over the return collection from GetProperties, but since the documentation states it is not recommended I was looking to understand why and what other option do I have?
The order simply isn't guaranteed; whatever happens.... Happens.
Obvious cases where it could change:
anything that implements ICustomTypeDescriptor
anything with a TypeDescriptionProvider
But a more subtle case: partial classes. If a class is split over multiple files, the order of their usage is not defined at all. See Is the "textual order" across partial classes formally defined?
Of course, it isn't defined even for a single (non-partial) definition ;p
But imagine
File 1
partial class Foo {
public int A {get;set;}
}
File 2
partial class Foo {
public int B {get;set:}
}
There is no formal declaration order here between A and B. See the linked post to see how it tends to happen, though.
Re your edit; the best approach there is to specify the marshal info separately; a common approach would be to use a custom attribute that takes a numeric order, and decorate the members with that. You can then order based on this number. protobuf-net does something very similar, and frankly I'd suggest using an existing serialization library here:
[ProtoMember(n)]
public int Foo {get;set;}
Where "n" is an integer. In the case of protobuf-net specifically, there is also an API to specify these numbers separately, which is useful when the type is not under your direct control.
For what it's worth, sorting by MetadataToken seemed to work for me.
GetType().GetProperties().OrderBy(x => x.MetadataToken)
Original Article (broken link, just listed here for attribution):
http://www.sebastienmahe.com/v3/seb.blog/2010/03/08/c-reflection-getproperties-kept-in-declaration-order/
I use custom attributes to add the necessary metadata myself (it's used with a REST like service which consumes and returns CRLF delimited Key=Value pairs.
First, a custom attribute:
class ParameterOrderAttribute : Attribute
{
public int Order { get; private set; }
public ParameterOrderAttribute(int order)
{
Order = order;
}
}
Then, decorate your classes:
class Response : Message
{
[ParameterOrder(0)]
public int Code { get; set; }
}
class RegionsResponse : Response
{
[ParameterOrder(1)]
public string Regions { get; set; }
}
class HousesResponse : Response
{
public string Houses { get; set; }
}
A handy method for converting a PropertyInfo into a sortable int:
private int PropertyOrder(PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
Even better, write is as an extension:
static class PropertyInfoExtensions
{
private static int PropertyOrder(this PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
}
Finally you can now query your Type object with:
var props = from p in type.GetProperties()
where p.CanWrite
orderby p.PropertyOrder() ascending
select p;
Relying on an implementation detail that is explicitly documented as being not guaranteed is a recipe for disaster.
The 'recommended approach' would vary depending on what you want to do with these properties once you have them. Just displaying them on the screen? MSDN docs group by member type (property, field, function) and then alphabetize within the groups.
If your message format relies on the order of the fields, then you'd need to either:
Specify the expected order in some sort of message definition. Google protocol buffers works this way if I recall- the message definition is compiled in that case from a .proto file into a code file for use in whatever language you happen to be working with.
Rely on an order that can be independently generated, e.g. alphabetical order.
1:
I've spent the last day troubleshooting a problem in an MVC 3 project, and it all came down to this particular problem. It basically relied on the property order being the same throughout the session, but on some occations a few of the properties switched places, messing up the site.
First the code called Type.GetProperties() to define column names in a dynamic jqGrid table, something that in this case occurs once per page_load. Subsequent times the Type.GetProperties() method was called was to populate the actual data for the table, and in some rare instances the properties switched places and messed up the presentation completely. In some instances other properties that the site relied upon for a hierarchical subgrid got switched, i.e. you could no longer see the sub data because the ID column contained erroneous data. In other words: yes, this can definitely happen. Beware.
2:
If you need consistent order throughout the system session but not nessecarily exactly the same order for all sessions the workaround is dead simple: store the PropertyInfo[] array you get from Type.GetProperties() as a value in the webcache or in a dictionary with the type (or typename) as the cache/dictionary key. Subsequently, whenever you're about to do a Type.GetProperties(), instead substitute it for HttpRuntime.Cache.Get(Type/Typename) or Dictionary.TryGetValue(Type/Typename, out PropertyInfo[]). In this way you'll be guaranteed to always get the order you encountered the first time.
If you always need the same order (i.e. for all system sessions) I suggest you combine the above approach with some type of configuration mechanism, i.e. specify the order in the web.config/app.config, sort the PropertyInfo[] array you get from Type.GetProperties() according to the specified order, and then store it in cache/static dictionary.

Dynamic Linq Library Help

I have the following class:
public class Item
{
public Dictionary<string, string> Data
{
get;
set;
}
}
and a list of it:
List<Item> items;
I need to filter and order this list dynamically using SQL-Like strings. The catch is, that I need to order it by the Data dictionary.
For example: Order By Data["lastname"] or Where Data["Name"].StartsWith("a"). I thought to use the dynamic linq library, but is there any way that my clients can write without the Data[]? For example:
Name.StartsWith("abc")
instead of
Data["Name"].StartsWith("abc")
?
You could add a property like this:
public class Item
{
public Dictionary<string, string> Data
{ get; set; }
public string Name { get { return Data["lastname"]; } }
}
//Call by: i.Name.StartsWith("abc");
Or an extension method:
public static class ItemExtensions
{
public static string Name(this Item item)
{
return item.Data["lastname"];
}
}
//Call by: i.Name().StartsWith("abc");
Or if it's a very commonly used method, you could add something like a .NameStartsWith():
public static string NameStartsWith(this Item item, stirng start)
{
return item.Data["lastname"].StartsWith(start);
}
//Call by: i.NameStartsWith("abc");
This doesn't have anything to do with the Linq Dynamic Query unit. That unit is for when you have actual fields/properties and the names of them will be given to you at runtime. In other words, you have a class like this:
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
And you want to be able to write a query like this:
var sortedPeople = people.OrderBy("FirstName");
You are trying to do the exact opposite of this - you have a class that does not have any actual properties, just an attribute dictionary, and you want compile-time safety. You can't have it; there's no way to guarantee that an item will be in the dictionary, especially when the dictionary is public and anyone can add/remove directly from it!
If there's some reason that you must use that specific class design, then you could conceivably write some wrappers as Nick has presented, but I wouldn't even bother - they're not actually providing any encapsulation because the Data dictionary is still wide open to the whole world. Instead, I would just provide a single safe getter method or indexer property and create a few constants (or an enum) with the names of properties you expect to be in there.
public class Item
{
public Dictionary<string, string> Data { get; set; }
public string GetValue(string key)
{
if (Data == null)
return null;
string result;
Data.TryGetValue(key, out result);
return result;
}
}
public class ItemKeys
{
public const string Name = "Name";
public const string Foo = "Foo";
}
And so on. Really the ItemKeys isn't that important, the safe GetValue method is what's important, because otherwise you run the risk of a NullReferenceException if Data hasn't been assigned, or a KeyNotFoundException if even one Item instance doesn't have that property. Using the GetValue method here will succeed no matter what:
var myItems = items.OrderBy(i => i.GetValue(ItemKeys.Name));
If you find you're writing a lot of repetitive code for the same attributes, then start worrying about adding shortcut properties or extension methods to the class.
I assume that you don't know the names of the properties at compile-time (in which case, you could simply define properties and wouldn't have this problem). I have two suggestions that you could try, but I didn't implement any of them myself, so I can't guarantee that it will work.
If you can use .NET 4.0, you could inherit from DynamicObject and implement TryGetMember method (which is called when you use o.Foo on an object that is declared as dynamic). Assuming that Dynamic LINQ works with DLR, it should automatically invoke this method for objects that inherit from DynamicObject. Inside the TryGetMember method, you would get a name of the accessed property, so you could perform a dictionary lookup. (However, this solution would work only if Dynamic LINQ integrates well with DLR).
In any case, you could do some basic parsing of the string entered by the user and replace for example Name with Data["Name"]. This would definitely work, but it may be a bit difficult (because you should probably at least check that you're doing the replace in correct context - e.g. not inside a string constant).
Regarding extension methods - I'm not sure if Dynamic LINQ handles extension methods (but, I don't think so, because that would require searching all referenced assemblies)

Categories

Resources