I'm basically re-asking this question as the only and accepted answer is not an answer to the question.
Is it possible to tell EF to use a class that subclasses EntityObject, like the one below, as the base class of generated entity classes?
public abstract class CustomEntityObject : EntityObject
{
<additional functionality>
}
The reason I'm asking is I want to stop adding interfaces and implementing them on all entity types in separate partial class files. By sub-classing EntityObject I could implement the additional functionality once only.
Update:
EF implicitly uses a .tt file to generate entity classes. By implicitly I mean you don't see the .tt file in your project. The solution is to add the template explictly (right-click on the .edmx designer and click "Add Code Generation Item...", then add "ADO.NET EntityObject Generator"). You then change a single value in the .tt:
string BaseTypeName(EntityType entity, CodeGenerationTools code)
{
return entity.BaseType == null ? "EntityObject" : MultiSchemaEscape((StructuralType)entity.BaseType, code);
}
changes to:
string BaseTypeName(EntityType entity, CodeGenerationTools code)
{
return entity.BaseType == null ? "CustomEntityObject" : MultiSchemaEscape((StructuralType)entity.BaseType, code);
}
You can use such hack (this is hack).
Create class "abstract class EntityObject : System.Data.Objects.DataClasses.EntityObject" in the same namespace with your entities. Then you can use this class as base class.
But if you want to create complex and beauty solution - use T4 templates, custom generation etc. You can find solutions here, here.
Thing is, that using default T4 template designer will generate entity classes inherited from EntityClass.
To use model designer and have ability to supply custom base class you need to download http://msdn.microsoft.com/en-us/library/ff477605.aspx (it's a description how to use it, before it was in add item>online templates, but at least on my vs2012 can't find it anymore, it tmay be that is gone for a reason) template and edit template files to inject your custom base class, but I think that most of programmers look at POCO for a reason, so may be better idea is to have classes that don't have persistence attached.
Related
I wanna generate C# protobuf code with customize attributes.
such as:
public sealed partial class LoginIn : pb::IMessage<LoginIn>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
[mycall] // customize attributes
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] // original
public LoginIn() {
OnConstruction();
}
... // rest code
With partial class, you can add attributes (and members) to the type, but you can't add attributes to individual members, so: you can't do anything simple here. Effectively, you'd need to tweak the code-gen itself (meaning: create your own version of the protoc addin), which is far from ideal.
The other option is manually editing the generated code - again: far from ideal.
Before doing either of those, I'd have to ask myself some serious questions about [mycall] and how important it is, what it does, and whether adding it to the serialization model is necessary, vs creating my own domain model that can have any attributes you want, and mapping between the domain model and the serialization model.
My problem is similar to this one, except that the code I want to use with protobuf-net was generated by the WSDL utility. "They tell me" that it's not appropriate to plan to modify the generated code (to add attributes).
It would be odd to write something to build a matching set of DTO classes, given that (other than the methods described) all the classes are already public (partial) classes marked with [Serializable] and have all public properties -- that is, they are very DTO-like already.
The simplest solution I've seen is to violate the rules and modify the code. If all strings in the generated C# file
public partial class
are replaced with
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public partial class
from my limited testing that will do the trick. Does a better solution exist? Is there something wrong with using that technique (other than that I'm modifying generated code)?
Type-level attributes in partial classes can be added in separate code files. All you need is a separate file with just:
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public partial class {}
it must also be in the right namespace, but you didn't say which, so probably:
namespace Foo {
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
public partial class {}
}
I used the OWLGrinder to create the assembly and imported the library into my project. That works fine. Now I want to write my own set of classes. Therefore I extended these with the equivalent of the assembly. But it just doesn't work.
The ontology holds a class named ManagementObject.
I created another Class (C#) called RealWorldObject:
public class RealWorldObject : ManagementObject
{
public RealWorldObject(string uri) : base(uri) { }
public RealWorldObject(string uri, RdfDocument rdfdocument) : base(uri, rdfdocument) { }
public RealWorldObject(RdfDocument rdfdocument) : base(rdfdocument) { }
public String getClassName()
{
return this.OwlClassName;
}
public static RdfDocument addRealWorldObjectIndividualt(RdfDocument rdfDocument)
{
Vehicle vehicle = new Vehicle("vehicle1", rdfDocument);
FixedEvent fxE1 = new FixedEvent("autoGekauft", rdfDocument);
fxE1.agent = new xmlns.com.foaf._01.Person("robert", rdfDocument);
vehicle.hasFixedEvent = fxE1;
return rdfDocument;
}
Which leads to the error:
ObjectManagement.Object.RealWorldObject does declare one (and only one) OwlClassAttribute. This is an implementation bug of the plugin.
How else should I extend the generated classes by the OWLGrinder.
Thx it is a long time ago that I used C#, so I'm kind of rusty.
The auto-generated classes produced by OwlGrinder.exe have not been designed for inheritance in mind. I am not saying it is wrong, it is just not designed for that. The auto-generated classes contain plenty of metadata defined as class attributes and inheritance hides all of that. The infrastructure counts on the presence of these attributes and if they are hidden, you get these runtime error messages.
Using Visual Studio Object Browser, take a look of the attributes over the auto-generated classes. OwlClassAttribute, SubClassOfAttribute, LightVersionAttribute are certainly mandatory. You may simply copy/paste the class attributes of ManagementObject on the top of your RealWorldObject class. I assume, it will work. But again, you might bump into additional show stoppers, as you do not follow the default routes ROWLEX has been designed for. This is a bit living on the edge :)
Instead of inheritance, you might consider reverse engineering your auto-generated assembly to C# using Reflector or other tools. Having the source code in your hand, you may modify the generated classes directly. You might make your ManagementObject class partial, and implement your additional methods in a separate file.
I am using Linq-To-SQL and I would like to attach an interface to each of my entities.
I can edit the designer.cs file and accomplish this.
However, when I make a changes to the dbml through the UI it rewrites the whole designer.cs and I lose my changes.
Am I just going to have to deal with it, or is there a way to get around it?
I am doing this in the designer.cs file(the IMatchable is a custom interface of mine):
public partial class Error : INotifyPropertyChanging, INotifyPropertyChanged, IMatchable
{
...
}
Don't edit the designer file; the beauty of partial classes is that you can create a separate file with just
public partial class Error : IMatchable
{ }
(assuming that we are using implicit interface implementaion by virtue of having properties that match the required interface)
Small word of caution though: if you are using VS2008 and you have MyClasses.dbml and MyClasses.designer.cs, do not call this file MyClasses.cs - there is a bug in VS2008 that makes this a nuisance (you have to keep moving the using directives inside the namespace, or the code-generator breaks) - fixed in VS2010 though.
Also, if it was a single interface, that every type in your model implemented, you can cheat by specifying that at the object base-type in the DBML. The designer doesn't show this option, but if you edit the DBML manually it works fine.
alt text http://img16.imageshack.us/img16/8085/datacontext.jpg
Above is the LINQ to SQL designer view for my data context.
Below is the relevant code that the designer generates:
Accessor for the abstract ActivityBase class:
public System.Data.Linq.Table<ActivityBase> ActivityBases
{
get
{
return this.GetTable<ActivityBase>();
}
}
The ActivityBase class and the list of subclasses:
[Table(Name="dbo.Activities")]
[InheritanceMapping(Code="1", Type=typeof(ActivityBase), IsDefault=true)]
[InheritanceMapping(Code="2", Type=typeof(Project))]
[InheritanceMapping(Code="3", Type=typeof(ProjectActivity))]
[InheritanceMapping(Code="5", Type=typeof(Task))]
[InheritanceMapping(Code="4", Type=typeof(Activity))]
public abstract partial class ActivityBase : INotifyPropertyChanging, INotifyPropertyChanged
{
Is there a way to generate accessor methods for the subclasses as shown in the inheritance mapping above (Project, Task, etc...) without doing it manually? I added them manually but then a change in the designer overwrites any manual changes.
Am i doing this wrong? should I not be making accessors for the sub classes? filtering from ActivityBase seems worse to me.
Thanks for any help on this.
Notice that LINQ to SQL creates partial classes. If you want to modify the automatically generated classes you can do so by declaring a partial class with the same name and adding the methods there. This way they won't get overwritten when you make a change in the designer.
I found this question answers what I wanted to know:
What is the .cs file under MyDataContext.dbml for?
since the data context is also a partial class I can use that file.