What is the substitution for partial property in C#? - c#

I have an application (mvc 3) where the code is autogenerated for the datacontext class. And I need to expand the functionality, so I created partial class with the same name. But I found that only "void methods" could be marked as partial, while I need kind of a partial property.
So, is there any way to expand property's functionality in C#?
Updated:
Here is the code:
public Table<Post> Posts
{
get
{
// writing info into Trace file
Log = Console.Out;
var result = this.GetTable<Post>();
Log = new LogLinqToSql();
SubmitChanges();
return result;
}
}
The thing is that if I make any change to the data model this code will disappear, so how can I move it to the "safer" place?

Sorry for using the answer field, the post is for the discussion above:
Can't you just wrap the property from the DataContext in another property in your class
e.g.
partial class NewClass
{
public Table<Post> NewProperty
{
get
{
DoHouseKeeping();
return this.PropertyFromOtherPartialClass;
}
}
}
Only the classes need to be marked as partial.

The solution for my problem (provide logging) is simple: In the autogenerated code there is a bunch of partial helper methods. And there is a method "OnCreated" which is called when the instance of MyTypeDataContext class is created. So, I just need to do the following:
public partial class WebStoreDataContext
{
partial void OnCreated()
{
// writing info into Trace file
Log = Console.Out;
Log = new LogLinqToSql();
SubmitChanges();
}
}
If You want to add Attributes to the properties this post provides all the information)

Related

c# auto generated partial class redefine property get set

I'm moving from mainly classic asp to .NET. So this may be a stupid question, but I can't find an answer.
I have an MVC App using Database First and Entity Framework. Now I would like to add some logic to the auto generated 'partial' classes. From what I have read it should be a matter of creating a new partial class with the same namespace and name. But when I do that I get an error "(This member is defined more than once)" and "Ambiguity between [partial class] and [partial class]". I understand what the error is saying, but I'm not sure how to resolve the problem.
I would like to add some logic to the set; accessor.
So in the generated class I have
public partial class QualityChecks
{
.....
public int DailyCount { get; set; }
...
}
in my new partial class I would like to add to the set code to make sure only values greater then 0 are added. If a negative value is added it needs to be logged and changed to 0
e.g. my new partial class is:
public partial class QualityChecks {
public int DailyCount {
set
{
DailyCount = value;
if it's < 0 log and set to 0
}
}
If that's not clear maybe this will help:
Currently I have loads of code that simply does
QualityChecks qc = new QualityChecks();
qc.DailyCount = enteredAmount;
....
db.QualityChecks.add(qc);
Rather then update that logic everywhere it would be nice to have it wrapped up in the QualityChecks class.
Is this the right way of going about it? If so what do I need to change to make this work?
Thank you in advance for any tips and help!
You cannot define the same members in two different files.
You can try to define a new wrapper property (eg. MyDailyCount) that add that extra logic and update the underlying DailyCount at the end so it get persisted to database.
public int MyDailyCount
{
get { return DailyCount; }
set
{
DailyCount = value;
// your extra logic
}
}

Using one view model in multiple windows

How can I use one view model for many windows in WPF? I need model to be updated from one window only and handle these changes in others (for ex. property 'Locked').
I have one view model incapsulating the most general info that should be used not only on the A (suppose it is 'Company') window but also on windows child window B (suppose it is 'Person'). So the 'General' view model should be determined by A entity but be passes to all children entity. While updating this view model on A window - we should se changes on all B windows.
public partial class A : WindowBase
{
private GeneralViewModel general;
public GeneralViewModel General
{
get
{
return this.general ?? (this.general = new GeneralViewModel ());
}
}
}
public partial class B : WindowBase
{
private GeneralViewModel general;
public GeneralViewModel General
{
get
{
return this.general ?? (this.general = new GeneralViewModel ());
}
}
public B(GeneralViewModel g)
{
this.general = g;
}
}
I wish the model should be updated only in A and B was simply displaying that changes were maid. In case I pass model as it is shown in this code or if I implement 'General' as property with getter and setter changes are not applied.
Thanks for any help.
You could use a singleton-class as your ViewModel.
Example:
public Window()
{
this.DataContext = ViewModel.Instance.
}
EDIT:
public GeneralViewModel
{
public DataType Model
{
get { return DataType.Instance; }
}
}
Now everytime you access the Model in one of your GeneralViewModels, it is locked for all others.
Initialise your view model in a static member somewhere and have the windows return the value as their GeneralViewModel.
In the scenario you mentioned, your GeneralViewModel is a kind of Dependency to both your Window classes and for these purposes you can use some of the available IoC containers or MEF built into .Net 4. You can register your Dependencies including the GeneralViewModel in some application startup event.
Below is some sample code that will make your GeneralViewModel instance to be then located from the container it is registered with (MEF in below case):
[Export(typeof(B))]
public partial class B : WindowBase
{
private GeneralViewModel general;
public GeneralViewModel General
{
get
{
return this.general ?? (this.general = new GeneralViewModel ());
}
}
[ImportingConstructor]
public B(GeneralViewModel g)
{
this.general = g;
}
}
To learn more about MEF,see these articles:
CodePlex
Ten Reasons to use the Managed Extensibility Framework
Managed Extensibility Framework Overview
An Introduction to Managed Extensibility Framework (MEF) - Part I
There are many other DI and IoC containers available as Open Source downloads.
There is no problem if you use MVVM. In this case your ViewModel will correspond to some View which is basically the UserControl and you can place it to as many Windows as you wish.
And When you implement MVVM you should also use INotifyPropertyChanged or ObservableCollections

Where is the code for the EDML generated Models?

I have built a data driven model by dragging my tables onto the empty designer of an edml. I know that I can establish a datacontext around my model, and that I can access each table as though it were a class, but where is the code for each of these models?
I ask because I want to add validation to the setters of each property on the class itself.
Look for a .dbml file on the root level of your project. Under that file, you will see a file called <someDB>.designer.cs.
However, (and you'll see this at the top of the designer file as well), you don't really want to make any changes to the classes in this file.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
If you want to make additions, you should look into creating Partial classes that extend the functionality of the generated classes.
Here is a sample partial class that I created to handle my validations:
namespace ETL_Framework_UI
{
[MetadataType(typeof(DataObjectMD))]
public partial class DATA_OBJECT:IValidatableObject
{
public class DataObjectMD
{
[Required(ErrorMessage="The object name is required")]
[StringLength(50, ErrorMessage = "Name cannot exceed 50 characters")]
public string OBJECT_NAME { get; set; }
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
ETLDbDataContext db = new ETLDbDataContext();
var field = new[] { "OBJECT_NAME" };
var param = db.DATA_OBJECTs.SingleOrDefault(r => r.OBJECT_NAME == OBJECT_NAME && r.OBJECT_ID != OBJECT_ID);
if (param != null)
{
yield return new ValidationResult("Object name is already in use. ", field);
}
NOTE Your partial class must be defined in the same namespace that you see at the top of your designer.cs file.
You do not want to edit the auto-generated classes themselves, this will lead to huge problems if you ever need to generate them again. You want to use partial classes with DataAnnotations instead. This way your validation/extra rules will be forever separated and easier to maintain.
Entity framework + validation annotation
If you are going to add validation maybe Entity Framework Code First is a better solution.

Using DataAnnotations with Entity Framework

I have used the Entity Framework with VS2010 to create a simple person class with properties, firstName, lastName, and email. If I want to attach DataAnnotations like as is done in this blog post I have a small problem because my person class is dynamically generated. I could edit the dynamically generated code directly but any time I have to update my model all my validation code would get wiped out.
First instinct was to create a partial class and try to attach annotations but it complains that I'm trying to redefine the property. I'm not sure if you can make property declarations in C# like function declarations in C++. If you could that might be the answer. Here's a snippet of what I tried:
namespace PersonWeb.Models
{
public partial class Person
{
[RegularExpression(#"(\w|\.)+#(\w|\.)+", ErrorMessage = "Email is invalid")]
public string Email { get; set; }
/* ERROR: The type 'Person' already contains a definition for 'Email' */
}
}
A buddy class is more or less the direction your code snippet is journeying, except your manually coded partial Person class would have an inner class, like:
[MetadataType(typeof(Person.Metadata))]
public partial class Person {
private sealed class MetaData {
[RegularExpression(...)]
public string Email { get; set; }
}
}
Or you could have your manually partial Person class and a separate Meta class like:
[MetadataType(typeof(PersonMetaData))]
public partial class Person { }
public class PersonMetaData {
[RegularExpression(...)]
public string Email;
}
These are workarounds and having a mapped Presentation class may be more suitable.
You need to either use a metadata "buddy" class or (my preference) project onto a presentation model instead of binding views directly to entities.

DSL Custom Constructor - only calling when created not loading

Info: VS2010, DSL Toolkit, C#
I have a custom constructor on one of my domain classes which adds some child elements. I have an issue as I only want this to run when the domain class element is created , not every time the diagram is opened (which calls the construtors)
public Entity(Partition partition, params PropertyAssignment[] propertyAssignments)
: base(partition, propertyAssignments)
{
if (SOMETHING_TO_STOP_IT_RUNNING_EACH_TIME)
{
using (Transaction tx = Store.TransactionManager.BeginTransaction("Add Property"))
{
Property property = new Property(partition);
property.Name = "Class";
property.Type = "System.String";
this.Properties.Add(property);
this.Version = "1.0.0.0"; // TODO: Implement Correctly
tx.Commit();
}
}
}
It looks like you are initializing some domain class properties from within the constructor. This is best done by creating an AddRule. AddRules are invoked when an instance of the domain class to which they are attached is added to the model. For example :
[RuleOn(typeof(Entity), FireTime = TimeToFire.TopLevelCommit)]
internal sealed partial class EntityAddRule : AddRule
{
public override void ElementAdded(ElementAddedEventArgs e)
{
if (e.ModelElement.Store.InUndoRedoOrRollback)
return;
if (e.ModelElement.Store.TransactionManager.CurrentTransaction.IsSerializing)
return;
var entity = e.ModelElement as Entity;
if (entity == null)
return;
// InitializeProperties contains the code that used to be in the constructor
entity.InitializeProperties();
}
}
The AddRule then needs to be registered by overriding a function in your domain model class:
public partial class XXXDomainModel
{
protected override Type[] GetCustomDomainModelTypes()
{
return new Type[] {
typeof(EntityAddRule),
}
}
}
For more information about rules, have a look at the "How to: Create Custom Rules" topic in the VS SDK documentation.
Note: the solution is based on the VS 2008 DSL Tools. YMMV.
Although not the correct approach (Paul Lalonde answer is the best),
here's how you may know, at any given time, if the model is being serialized (= loading):
this.Store.TransactionManager.CurrentTransaction!= null &&
this.Store.TransactionManager.CurrentTransaction.IsSerializing

Categories

Resources