I'm just wondering if there is a way to Map Properties from a class to an interface with out changing their names.
Say you imported some entities from a Database
public partial class Post
{
public int PostId {get; set;}
}
public partial class Book
{
public int BookId {get; set;}
}
and an interface:
public interface IHasID
{
int Id {get; set;}
}
is there a way to inherit from this interface and just map the Properties using attributes like:
public partial class Post : IHasID
{
[MetadataTypeAttribute(typeof(IHasID.Id))]
public int PostId;
}
I just want a simple way to do this without wrapping all of the code or changing the database. Is there a way to wrap the parital class to point its property as an interface property?
You could create an ID property which gets and sets your object's appropriate ID, like this:
public partial class Post : IHasID
{
[NotMapped]
public int Id
{
get { return PostId; }
set { PostId = value; }
}
public int PostId { get; set; }
...
You would of course do the same thing for Book.
I'm not sure if it's worth pointing out just for the sake of knowledge that, if it were vb.net, you could do it just like this:
Partial Public Class Post
Implements IHasID
Public Property PostId As Integer Implements IHasID.Id
End Class
Related
I have common field in all tables
public Guid UserId { get; set; }
How can I fill in this field without repeating the code?
I want to do it using the interface.
It would be better to create base class and inherit from it in each model class.
public class BaseModel
{
public Guid UserId { get; set; }
}
public class Table : BaseModel
{
}
If you use an interface, you will still need to implement the property in every class.
i'm using EF Core with TPH.
Let's say i have Base-Class called "BlogBase"
public class abstract BlogBase
{
public int BlogId {get;set;}
}
and in addition i've two Classes which inherit from BlogBase
public class RssBlog : BlogBase
{
public string Name {get;set;}
}
public class Blog : BlogBase
{
public string Address {get;set;}
}
At least i've another Class which use Blog as a Property (FK)
public class Website
{
public int WebsiteId {get;set;}
public int BlogBaseId {get;set;}
public virtual ICollection<BlogBase> Blog {get;set;}
}
The problem now is, that when i am try to change the "Blog" Property of a Website-Object, the value change (in-memory - the debugger shows the right value), but when i call SaveChanges it does not have any effect to the database. So at least the value does not get updated at the database.
website.Blog = new RssBlog();
or
website.Blog = new Blog();
Do you guys have any idea why it's not working?
There is no exception when i call SaveChanges().
Thanks!
I have the following interface:
public interface IReport
{
int ReportId {get; set;}
}
I have an entity that has identity column property:
public int PaymentReportId {get; set;}
I need the PaymentReport to implement IReport
Inside my PaymentReport.cs I did:
public int PaymentReportId {get; set;}
public int ReportId {
get => PaymentReportId;
set {} //no need to ever set this;
}
Otherwise the compiler was complaining about no setter implemented.
Is there a cleaner way to do this?
If you try to adhere to SOLID there is principle called interface segregation.
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
With your approach the principle is obviously violated as class PaymentReport does have property setter which is essentially not needed.
Consider to split the IReport to IReportRead and IReportWrite and implement only what is necessary.
public interface IReportRead
{
int ReportId { get; }
}
public interface IReportWrite
{
int ReportId { set; }
}
public class PaymentReport : IReportRead {//...}
That way you have clear abstraction and you are not polluting the implementation.
I removed, the set from the ReportId of IReport and then implemented in the class.
public interface IReport
{
int ReportId { get; }
}
public class PaymentReport : IReport
{
public int PaymentReportId { get; set; }
public int ReportId
{
get => PaymentReportId;
}
}
As others said, the cleanest thing would be to change the interface or split into
several interfaces. Here is an example of splitting interface into two and use them in both the get scenario and the get, set scenario:
interface IFooGet
{
int Id { get; }
}
interface IFooSet
{
int Id { set; }
}
public class FooGet : IFooGet
{
public int Id { get; }
}
public class FooGetSet : IFooGet, IFooSet
{
public int Id { get; set; }
}
If that is not possible (maybe you don't own the code for the interface?) you might throw an exception if someone tries to call the property.
class PaymentReport : IReport
{
public int PaymentReportId {get; set;}
public int ReportId {
get => PaymentReportId;
set => throw new NotSupportedException();
}
}
Just having a empty body in the set may sometime lead to error hiding https://en.wikipedia.org/wiki/Error_hiding if some code in the future tries to call setter and makes the assumption that the setter actually does something meaningful
I am creating an application using Entity Framework 6.0 and Database-First approach. After I updated model from the database, I realised the essential need models to be derived from a BaseEntity class. The reason is that I need the base class to access the Id property using the BaseEntity class because the model class is often not specified.
My current solution is simple. According to Luke answer I implemented the partial class schema and directly derived a model class from RootEntity. In fact, the RootEntity class has the Id property as the model classes do. The compiler says CS0114 warning that classes should override properties. Since the model is autogenerated it cannot override properties.
What is the best practice to solve the particular issue? I'd like to implement a cleared architecture but this unpretty pattern may confuse anyone who reads my code.
// autogenerated EF code
public partial class Education
{
public int Id { get; set; }
public string Title { get; set; }
public System.DateTime AwardDate { get; set; }
public Nullable<int> PersonId { get; set; }
public virtual Person Person { get; set; }
}
// the base custom class I wont others to be derived from
public class RootEntity
{
public int Id { get; set; }
}
// partial class deriving
public partial class Education : RootEntity { }
EDIT:
The best solution I've found is to release the RootEntity class as an interface IPrimary. It also doesn't allow to directly create an object and provides a clearer definition of the required functionality.
public interface IPrimary
{
int Id { get; set; }
}
The best solution I've found is to release the RootEntity class as an interface IPrimary. It also doesn't allow to directly create an object and provides a clearer definition of the required functionality.
public interface IPrimary
{
int Id { get; set; }
}
public partial class Education : IPrimary { }
I'm using Entity Framework.
My Customer Entity is:
public partial class Customer
{
public virtual int ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string CompanyName { get; set; }
}
And I have a BaseEntity class which is inherited by partial Customer class.
public class BaseEntity
{
public virtual int ID { get; set; }
}
public partial class Customer : BaseEntity
{
}
After that, I created a generic method as follows:
public static int GetId<T>(T entity) where T : BaseEntity
{
// id is zero after savechanges
var id = entity.ID;
return id;
}
My problem occurs when I want to get the id after SaveChanges() in the generic method, it's zero.
My test code is:
var db = new ContextDb();
db.Customers.Add(customer);
db.SaveChanges();
WriteLine($#"{customer.ID}"); // OK
WriteLine($#"{GetId(customer)}"); // Not OK --> ZERO
Thanks everyone for taking the time to try and help explain.
It is caused by the fact that, indeed, you have two ID fields: one (hidden) from BaseEntity (which has a value of zero) and one from Customer (which is not zero). Try to override the ID property or simply remove it from the Customer class declaration:
public partial class Customer
{
public override int ID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string CompanyName { get; set; }
}
You can also mark the ID property and BaseEntity class as abstract to force to override the ID property in inherited classes:
public abstract class BaseEntity
{
public abstract int ID { get; set; }
}
NOTE: Previously accepted answer is not good advice, while it satisfies the issue, for new developers it encourages them to think that it is normal to make all properties virtual or common practice to override every virtual member from the base class.
Because BaseEntity already defines ID, you SHOULD NOT be trying to re-implement ID in the inheriting class unless you specifically want to augment the original implementation.
In this case we are not offering any different implementation to the base and so should not be trying to override it.
Conversely, if you do want to force every inheriting class to implement a function or property in their own way, then mark it as abstract, not virtual, and follow this advice.
Putting all 3 class definitions in-line, I would recommend the following solution:
public class BaseEntity
{
public int ID { get; set; }
}
public partial class Customer : BaseEntity
{
}
public partial class Customer
{
// ID is provided from the base!
//public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
}
Using virtual properties becomes dangerous as a design choice because there is a gray area where auto-properties might or might not be implemented in the base or other inheriting classes. If all classes in the inheritance tree use auto-properties, then there is no issue, however when any traditional getter or setter that is not auto is overriden, if the override does not call back to the base implementation, then any references to the fields or placeholders that were implemented in the base will not have their values set.
which is pretty close to the situation that OP has raised.
Specifically with ORM tools like EF, I would caution making the ID property virtual or abstract at all.
The ID is too important to leave to chance.
If you are using virtual properties to support Lazy Loading, in EF you only need to make navigational properties virtual to support this, not every property on a class.