I have some objects which have been created automatically by linq2SQL.
I would like to write some code which should be run whenever the properties on these objects are read or changed.
Can I use typical get { //code } and set {//code } in my partial class file to add this functionality? Currently I get an error about this member already being defined.
This all makes sense.
Is it correct that I will have to create a method to function as the entry point for this functionality, as I cannot redefine the get and set methods for this property.
I was hoping to just update the get and set, as this would mean I wouldn't have to change all the reference points in my app. But I think I may just have to update it everywhere.
Not sure about read, but you could track changes of your objects. E.g. there is PropertyChangedEventHandler on auto generated entities.
So what have you do is to white a partial class (let's assuming you have a Person entity):
public partial class Person
{
public Person()
{
this.PropertyChanged +=
new PropertyChangedEventHandler(Person_PropertyChanged);
}
protected void Person_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// your code here
}
}
What I did when I wanted to do this was make the property private/inaccessible (since this can be done as part of the DBML definition without editing the generated code), and give it a different name than the property I want to expose. Then I implemented a public wrapper property in a partial class, using the name I wanted to expose. Then (if you want to be really fancy) implement a LINQ provider that can convert queries that refer to the wrapper properties to queries that refer to the underlying properties. I have done all this and it's been working well, but the custom LINQ provider was tricky.
Unless you modify the generated code that was made, and then add additional code to the setter (such as using the pattern like in WPF, with INotifyPropertyChanged), then this would be impossible.
Related
I am trying to implement a very simple and more importantly optional object tracking system similar to how entity framework tracks object changes (How change tracking works in Entity Framework).
I have a base class that all other objects inherit from. This class has 1 boolean field called modified. The explicit solution to this is to update every setter on all properties of other classes to set modified = true when the setter is triggered. This solution has been presented in detail here Create an event to watch for a change of variable.
I want a more implicit solution to this. I have a lot of objects and a LOT of properties. Updating the setter is incredibly messy. I don't want to directly mimmic how entity framework does things because it is too expensive for my current requirements. I want a list of objects that i can loop to check of modified == true. This allows me to optionally track object and quickly check if they have changed without having to trigger an update for each individual object. Is there a way that i can set some sort of listener on all of the property getter and setters implicitly?
I know this code doesnt exist, but does .NET have a way to monitor the object to see if it has changed.
[OnChange=ObjectChanged()] //maybe this way
public class MyClass
{
bool modified {get; set;}
public MyClass() : OnChange(ObjectChanged) //or this way
{
}
private void ObjectChanged()
{
modified = true;
}
}
As i mentioned, i dont want to update every setter or copy what entity framework does.
There's nothing built-in in the .NET framework for this, but there are third-party tools to do exactly that.
One such option would be Fody/PropertyChanged, which injects OnPropertyChanged calls into all automatic property setters of your classes. You can subscribe to the PropertyChanged event and update your Boolean flag. As an additional bonus, (a) you get the name of the property that changed and (b) other classes (e.g. your UI framework) can subscribe to the event as well.
I create a desktop application using C# + EF 4.0. I'm aware that it's normal to add a custom method to Entity Framework EntityObject using partial classes:
public partial class EntityModel: EntityObject{
public void MyMethod() { ... }
}
But I need to add a custom field to store an information that I don't want to hold in database.
So would it be normal or is there any way to do it?
Sure, just add the property you need like:
public string MyCustomField { get; set; }
But bear in mind that it's stateful for that object so it's not going to persist anywhere unless you do that yourself and it's going to hold a different value for each object, unless of course you made it static, but I would strongly recommend against that.
As long as it's related to the class and doesn't really belong somewhere else, then it's completely normal.
I have several navigation properties from a 'Users' table to a 'Reports' table. The navigation properties that are generated are obviously accessed like this:
USER.REPORTs.Where(x => ...)
USER.REPORTs2.Where(x => ...)
USER.REPORTs3.Where(x => ...)
The first one is user createdId, second UserApprovedId etc... basic stuff.
These are extremely difficult to interpret. Its difficult to tell which property you are navigating without accessing the EDMX and checking the navigation property.
Now I know I can create my own End1/End2 navigation properties the properties manager but these are lost if the Model is recreated.
Is there a way around this?
I have not tried this, but here's an idea: since all the entity types are partial classes why not wrap the navigation property generated by Visual Studio in another property with a convenient name?
In your designer file you'll have something like this:
public partial class MyEntity : EntityObject
{
#region Navigation Properties
public EntityCollection<MyOtherEntity> Other_Entities1
{
// ...
}
#endregion
}
You can then create another file in which to wrap the navigation property:
public partial class MyEntity
{
public EntityCollection<MyOtherEntity> OtherEntities
{
get { return Other_Entities1;}
}
}
You'll use the property above throughout your code and since the same logic is used when Visual Studio generates the .edmx file the wrapped property won't change.
Even if the wrapped property will change its name you'll need to adjust the code in a single place.
I'm not sure if I'm understanding your problem correctly, but it sounds like you just want a "cleaner" way to access the results of a REPORTs.Where(...) LINQ query directly from the USER object. If that is the case, I suggest creating extensions of the USER object like this:
public static class UserExtensions
{
public static List<REPORT> ReportsWithSomeCondition(this USER user)
{
return user.REPORTs.Where(...).ToList();
}
}
And the way you can cleanly call this is:
List<REPORT> results = USER.ReportsWithSomeCondition()
If I totally missed the point, please clarify your question and I will delete this answer.
I think i have the same problem as i understand from your question.
You want to keep your navigational properties names as clear as you can but whenever recreate your Model from edmx ?!.
Actually i hope if there is a better solution but here what I'm doing :
Name your relations in DataBase a good names like : FK_Users_CreateUserReport, FK_Users_ApprovedUserReport ... or any suitable names we'll then rename the navigational properties as ApprovedUserReport and CreateUserReport so on ...
make a helper code to execute whenever you recreate your Model and this code will open your edmx file and makes update to all navigational properties you want something like this:
// file here is the path to your edmx file
if (!string.IsNullOrEmpty(file))
{
var ns = XNamespace.Get("http://schemas.microsoft.com/ado/2008/09/edm");
var doc = XDocument.Load(file);
var list = (from xElem in doc.Descendants(ns + "NavigationProperty")
where xElem.Attribute("Name").Value.StartsWith("REPORTs"))
select xElem).ToList();
foreach (var item in list)
{
var newName = item.Attribute("Relationship").Value.Split('_').LastOrDefault();
if (!newName.Contains("."))
item.SetAttributeValue("Name", newName);
else
{
var ss = newName.Split('.').LastOrDefault();
}
}
doc.Save(file);
MessageBox.Show(list.Count.ToString());
}
Final thing if you used Code Only pattern then this problem is gone but in that case you should keep your Model in agreement with your DataBase by hand.
You have to put all your custom entity code in separate code files using the partial class mechanism. This allows the generated code to be generated without your custom code to be affected.
Wahid's answer seems to be the best one for long term maintenance. We considered implementing interface properties in the Partial Class we use as a "Buddy Class" for extensions and setting up Metadata linking. But then the properties in the T4 template we are Interfacing would still be public and they should be private.
To improve upon Wahid's suggestion; we chose to instead of changing the standard of how we name Foreign key relationships, extend them.
FK_Users_Report_CreateUserReport would actually be our solution. The standard naming convention for the first 2 values is maintained and in the update model code you can force it to only change the navigation property names of ones with the 3rd underscore and 3rd value on it. Ensuring you do no effect anyone other navigation property names if they didn't follow the standard naming convention for Foreign Keys in the DB.
I have a generic editor in ASP.NET page for editing lookup values for different database tables.
The code behind uses a base class which handles 99% of the work across all the different lookups in the system.
A C# class is passed in to the base class from the code behind as below.
public class LookupPageBase : System.Web.UI.Page
{
protected IEditableLookupManager LookupManager
{
get
{
return this.lookupManager;
}
set
{
this.lookupManager = value;
}
}
}
public partial class LookupsEditor : LookupPageBase
{
this.LookupManager = new ConcreteManagerClass();
}
A different C# class is passed into the lookup Manager property for each lookup. I could use the factory pattern to avoid a big if then else in the code behind. However, I was wondering if the same effect could be achieved via a subclass of the code behind e.g.
public partial class LookupsEditorSubClass : LookupsEditor
{
public LookupsEditorSubClass() {
base.LookupManager = new ConcreteManagerClass();
}
}
Questions:
1) This would require the code behind class to be dynamically set..... Can the code behind class be dynamically set and is it even possible to inherit from a partial class?
2) If using a factory instead do I just need to accept a big if then else?
Any chance that you could use MVC for this? I see that you have included .NET 3.5 in the tags, so there is no real technical reason why you shouldn't.
The reason I ask is that this problem would be easily solved using MVC. Only the model would change between your different cases.
Update: Following your comments, I think that the Factory approach is probably best for you. Messing around with the codebehind classes has resulted in nothing but trouble for me in the past. Rather than changing the codebehind class, why don't you use usercontrols for the editing. Then, you could load a different usercontrol depending on the particular requirements of the entity that you are editing. This could be provided by a factory.
I need to know if there's any way (or another distinct approach) to an attribute knows something about what is being decorated for him. For example:
class Cat
{
public Cat() { }
[MyAttribute]
public House House { get; set; }
}
Inside MyAttribute I must do some preprocessing with the house object...
class MyAttribute : Attribute
{
public MyAttribute()
{
var ob = // Discover the decorated property, do some changes and set it again
}
}
I don't know if it's the better way, neither if it actually can be done,
This is not how attributes work. They are just compile time metadata added to something. They don't accomplish anything by themselves. At runtime, code can use that metadata to do things.
UPDATE: Basically, as I understand, you are trying to accomplish two things. The first is to tell the repository not to load some properties. Attributes can be used for this purpose but the repository code should use reflection on the entity type and see what it shouldn't load in the first place. The second thing is that you want to have the property loaded as it's called for the first time. You need to check if it's already loaded or not on each call and load it the first time it's called. This can be achieved by manually inserting such a code or using something like PostSharp which post-processes code and can inject method calls automatically by looking at the attributes. Probably, this is what you asked for in the first place.
What you want is the Policy Injection application block in EntLib.
Developers can use the Policy
Injection Application Block to specify
crosscutting behavior of objects in
terms of a set of policies. A policy
is the combination of a series of
handlers that execute when client code
calls methods of the class and—with
the exception of attribute-based
policies—a series of matching rules
that select the classes and class
members (methods and properties) to
which the application block attaches
the handlers.