In my VS2008 SP1, .NET 3.5 SP1 project, I have different classes that contain different properties.
I use C#3.0 auto properties a lot.
Some of these properties need to be collections. Since I want to make it simple, I use ReadOnlyCollection<T> for these properties.
I don't want to use IEnumerable<T> since I want random access to the elements.
I use Code Analysis (FxCop rules) and I get the CA2227 warning.
I don't understand why does ReadOnlyCollection<T> should have a set method while it can't be changed... The set method can only do exactly what the property can do.
Example:
using System.Collections.ObjectModel;
namespace CA2227
{
public class MyClass
{
public ReadOnlyCollection<int> SomeNumbers { get; set; }
}
}
CA2227 : Microsoft.Usage : Change 'MyClass.SomeNumbers' to be read-only by removing the property setter. C:\Users...\Visual Studio 2008\Projects\CA2227\MyClass.cs 7 CA2227
A ReadOnlyCollection cannot be changed, but there's no reason why a property with a setter that is of type ReadOnlyCollection can't be changed to refer to a different ReadOnlyCollection. If you want the SomeNumbers property to be immutable, then it needs to be both of a read-only type, and also have a non-public setter.
EDIT
If you're convinced in what you want, then although FxCop is correct to warn you, you are happy with the warning. If you want to get rid of it, then include a SuppressMessage attribute at that point - as long as you also define a CODE_ANALYSIS constant in the project properties before you build, FxCop will honour that attribute and just not issue that particular warning on that particular occasion.
It's rather odd to block changes to the contents of the collection without also blocking changes to the collection itself. If you want to be able to set the collection from within your class while conserving the use of automatic properties, you could use a private setter. e.g.:
public ReadOnlyCollection<int> SomeNumbers { get; private set; }
Consider using
public class MyClass
{
public IReadOnlyList<int> SomeNumbers { get; set; }
}
ReadOnlyCollection = http://msdn.microsoft.com/en-us/library/ms132474(v=vs.110).aspx
IReadOnlyList = http://msdn.microsoft.com/en-us/library/hh192385(v=vs.110).aspx
The problem with ReadOnlyCollection, is that it still inherits from ICollection, and still has .Add, even though documentation say it will throw - http://msdn.microsoft.com/en-us/library/cc672239(v=vs.110).aspx
Related
Using EF with Winforms in C#. I’d like to add full custom properties to our entities, using partial classes. All entities already have partial classes with validation stuff and some more so I’d just add the properties that I need. By full property I mean property with getter and setter so not just a computed/readonly property. I want to this mostly to get around working directly with some DB mapped properties which are badly designed or have other problems.
For example, one case would be like this:
// entity class, generated
public partial class Customer
{
public string Spot {get;set}
}
// partial class, manually changed
public partial class Customer
{
public int? xxxSpot
{ get { return Int32.Parse(Spot.Trim()); } // some code omitted
{ set { Spot = value.ToString().PadLeft(5); }
}
So my custom properties will be built around existing, DB mapped properties of the entity. I’d like to use these custom properties like normal ones, ie to bind them to UI controls and so on. I’ve tried one and so far it works great.
Is this a good idea? If not, why ? And what else should I consider when doing this?
You have answered your own question - it works and there is no reason why to not do that. If you want to improve design of your entities you can even try to change visibility of your mapped properties to ensure that other classes must use only your custom properties with additional logic.
Is it possible to have Code First data classes declared with internal access as shown:
internal class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
I have a requirement that classes and its properties should not be visible outside of the assembly.
As long as your DbContext derived class that exposes your class to EF is in the same assembly, you should be able to. I don't happen to design my apps that way as I prefer more separation. But the context should be able to build the model and it should be able to interact with the classes (e.g. execute queries, save changes etc) if they are in the same assembly since it will have access to the internal class. Even with the various odd things we tried and wrote about in the Code First book, I never happened to try this particular scenario.
I am pretty new to entity framework, but given a simple object like this:
public class Country
{
public string Name { get; set; }
[Key]
public string Code { get; set; }
public bool IsPostalCodeRequired { get; set; }
public ICollection<Province> Provinces { get; set; }
}
returned by a DbContext, the Provinces property is null. If I use the Include method on my linq statement to include provinces, then it works. But I was wondering if there's a way to load them when I actually access the property? I know there's performance concerns to think about here, but I just want to know how to do it.
Thanks,
Make sure ObjectContext.ContextOptions.LazyLoadingEnabled is true. This is the default for a new project.
If using pure POCO entities, lazy loading can't work (think about it). So you can use POCO proxies. Again, this is the default, but making lazy loading work with POCO proxies requires that all the relationship properties are declared virtual, and yours aren't.
Craig said it all. Just wanted to say by default ObjectContext has LazyLoading turned off . Although when you create new .net 4.0 project, the model designer explicitly turns it on for u for .net 4.0 projects. Its turned off because EF needs to preserver legacy behavior of .net 3.5 when lazy loading was not available. However as you may notice that you are using Dbcontext which is new and has no dependency to .net 3.5. Hence LazyLoading would be enabled by default to give you seamless experience.
I'm using entity framework designer to build entities. I found the designer really hard to use because it overwrite all your manually change after each model update using the designer. How did you round off this problem? Thanks!
What sorts of things are you manually changing? The entity still has to be mappable to the database schema.
You can extend or add functionality by declaring a partial class.
Don't make any change to the entities in the generated file -- I think it says that in the header.
All of the entities are generated as partial classes, which means you can declare "more" of the class elsewhere.
Here is an example:
public partial class Name
{
public string First { get; set; }
}
public partial class Name
{
public string Last { get; set; }
}
Although I have two different class declarations, potentially in different files and folders within the project, it gets compiled as one class.
I can now use the Name class like this:
var name = new Name();
name.First = "Jane";
name.Last = "Doe";
As you can see, the properties from both declarations are unified in an object of type Name.
To apply this to EF, leave the partial entity class alone, and declare a separate partial class with the same name to add functionality.
There is an alternative third-party tool. For more information, refer this. Currently, Devart Entity Developer doesn't include the Update From Database functionality. The Update From Database feature is on our roadmap.
This is what reflector gives:
public int Int1 { get; set; }
public string StringA { get; set; }
// Fields
[CompilerGenerated]
private int <Int1>k__BackingField;
[CompilerGenerated]
private string <StringA>k__BackingField;
The problem is that C# specification doesn't explicitly specify how backing fields for automatic properties are named.
This can be a problem for binary serialization (from book C# 3.0 in a Nutshell).
Are there any other problems with auto-properties ? Should MS specify this in C# specs ?
I don't think MS should specify a name - I think it's more reasonable to avoid binary serialization, which is always going to be somewhat brittle in my opinion. (Java serialization is similarly brittle.) If it relies on field names (and there may be a way of getting round that by attributing your properties - I'm not sufficiently experienced with binary serialization to know) then it's restricting implementation changes quite nastily already.
My biggest problem with automatic properties is that there's no way of creating genuinely readonly properties (with readonly backing fields). I've ranted about this before though...
I don't like the following about auto-properties:
It is not possible to place break points on auto-properties.
The fields in the class are obvious, you will have to examine the fields as well as the properties to know what are the fields in the class. Where if they are not used, then you can just inspect the fields region.
Removes the ability to decorate the underlying fields with readonly, volatile, etc.