How to relate two unrelated foreign keys back to the same entity - entity-framework-5

Using EF code first, I created compound primary key on Packages and Services consisting of Id and Member_Id.
Then I made foreign keys from both of those tables into Promises.
As you can see it didn't relate the two foreign keys back to the same Member thus allowing the package member to be different than the service member. This is not what I intended.
I intend to have Promises just have a single Member_Id column and reuse it in both foreign keys. In problem terms, I intend for promises to only have services of the member that owns that promise's package.
I can easily do this in the database. See this fixed diagram:
This features compound foreign keys from Promises back to Packages and Services.
How can I attribute my classes in EF to achieve this result?
Is my only option to Database First migration and check and see what it does to mimic what I did manually in the database diagram editor?

I had to:
Fix my database the way I wanted it
Create a new Class Libray Project
Add Entity Framework Model. Choose Code First from Existing Database
Look at the differences between my classes and the generated classes from Database First, and see which ones I need to apply to my model. In this case, I found that the only way to create the foreign keys I wanted was with code not attributes and this is done in the OnModelCreating routine in the model (DbContext) class:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Member>()
.HasMany(e => e.Packages)
.WithRequired(e => e.Member)
.HasForeignKey(e => e.Member_Id);
modelBuilder.Entity<Member>()
.HasMany(e => e.Products)
.WithRequired(e => e.Member)
.HasForeignKey(e => e.Member_Id);
modelBuilder.Entity<Member>()
.HasMany(e => e.Services)
.WithRequired(e => e.Member)
.HasForeignKey(e => e.Member_Id);
modelBuilder.Entity<Package>()
.HasMany(e => e.Promises)
.WithRequired(e => e.Package)
.HasForeignKey(e => new { e.Package_Id, e.Member_Id })
.WillCascadeOnDelete(false);
modelBuilder.Entity<Service>()
.HasMany(e => e.Promises)
.WithRequired(e => e.Service)
.HasForeignKey(e => new { e.Service_Id, e.Member_Id })
.WillCascadeOnDelete(false);
}

Related

injecting different implementations and configurations of same interface into different clients

Suppose I have an interface IStorage and multiple implementations of it, e.g.:
class FileStorage : IStorage
{
public FileStorage(string filePath)
{
}
}
class HttpStorage : Storage
{
public HttpStorage(IHttpClient httpClient)
{
}
}
Now I have multiple classes that I want to register in my application and each of them needs a different IStorage instance.
All instances of ClassA (implementing and registered via IClassA) need a singleton FileStorage with "C:\Temp\foo.txt" as filePath.
All instances of ClassB (implementing and registered via IClassB) need a singleton FileStorage with "C:\Temp\bar.txt" as filePath.
All instances of ClassC (implementing and registered via IClassC) need a singleton HttpStorage with the registered singleton of IHttpClient.
How can I achieve the above without falling back to creating most of the dependency graph manually?
The primary question to ask every time you think you need this is: Do I violate the Liskov Substitution Principle. You are breaking the LSP in case the implementations aren't interchangeable for one another. If ClassA breaks when you inject an HttpStorage into it, you are breaking the LSP. In that case, you should give each implementation each own abstraction, such as IFileStorage and IHttpStorage.
My first impression is that you are not violating LSP. Simple Injector v3 contains a RegisterConditional method that allows you to do conditional registrations. With Simple Injector v3.1 you can make the registration as follows:
Lifestyle transient = Lifestyle.Transient;
container.RegisterConditional(typeof(IStorage),
transient.CreateRegistration(() => new FileStorage(#"C:\Temp\foo.txt"), container),
c => c.Consumer.ImplementationType == typeof(ClassA));
container.RegisterConditional(typeof(IStorage),
transient.CreateRegistration(() => new FileStorage(#"C:\Temp\bar.txt"), container),
c => c.Consumer.ImplementationType == typeof(ClassB));
container.RegisterConditional(typeof(IStorage),
transient.CreateRegistration(() => new HttpStorage(new HttpClient()), container),
c => c.Consumer.ImplementationType == typeof(ClassC));
The RegisterConditional overload that accepts an Registration instance is new in v3.1.

ServiceStack Ormlite Select Expression

I am building a service using ServiceStack and using OrmLite to communicate with database. I found following example in ServiceStack OrmLite Documention:
db.Select<Author>(q => q.Earnings <= 50);
OR
db.Select<Author>(q => q.Name.StartsWith("A"));
I am trying it with my class User, but unable to find a overload for method "Select" which allows me to do mentioned stuff. In my case q is a linq expression not an instance/reference for generic class type (User in my case). Following is my code:
db.Select<User>(q => q.Where(x => x.LastName == "XYZ"));
and i want it to be like:
db.Select<User>(q => q.LastName == "XYZ");
Please let me know if that is an extension method which i am looking for and how can i use that?
The Type that gets selected is the table is looking at, e.g:
db.Select<Author>(...) //Author
db.Select<User>(...) //User
See the answers on this earlier question for selecting a subset of data with OrmLite.

Extending Service/IService to add common dependencies

I have the need to extend Service/IService to allow me to register additional resources like other DB connections and custom classes that each individual service may need to get a handle to.
Is the proper way to do this to subclass Service? Also, it is not clear to me if I have another (say) IDbConnection how Funq figures out which Property to inject the value into.
If you have multiple services with the same type you need to register them in funq with a name. Unfortunatly I don't think funq can autowire the properties correctly so you need to manually resolve them.
container.Register<DataContext>("Security", x => new SecurityDataContext());
container.Register<DataContext>("Customers", x => new CustomersDataContext());
container.Register<DataContext>("Reporting", x => new ReportingDataContext());
container.Register<IReportRepository>(x => new ReportRepositoryImpl(x.ResolveNamed<DataContext>("Reporting")));
An alternative approach would be to create a unique interface (even if it has no members) for each type and then use that in funq. This would allow autowiring
container.Register<ISecurityDataContext>(x => new SecurityDataContext());
container.Register<ICustomersDataContext>(x => new CustomersDataContext());
container.Register<IReportingDataContext>(x => new ReportingDataContext());
// this could just be autowired
container.Register<IReportRepository>(x => new ReportRepositoryImpl(x.Resolve<IReportingDataContext>()));
If you still really need to extend Service you can just use standard inheritance in c#
public abstract class BaseService : Service
{
// custom things go here
public string Example() {
return "Hello World";
}
}
public class ReportsService : BaseService
{
public string Get(ListReports request) {
return Example();
}
}
You can configure other DB connections easily without extending the Service , but by just wiring them in the configure method in the AppHost.cs file.

Specify a conversion for an interface with automapper

Most of my EF objects have a TenantId Property. The system never have to handle the tenantId it's all taken care for before the SaveChanges(). I want to write an automapper map that will always ignore the TenantId Field.
I've tried
Mapper.CreateMap<IDomainObject, ITenantData>()
.ForMember(m => m.TenantId, a => a.Ignore());
You can handle it using mapping inheritance. For instance:
Mapper.CreateMap<IDomainObject, ITenantData>()
.Include<DomainObject1, TenantData1>()
.ForMember(m => m.TenantId, a => a.Ignore());

Must resolve to top-level member

I tried the following map:
CreateMap<ThemeNewModel, CreateThemeOrder.ThemeModel>()
.ForMember(d => d.Subject.Id, o => o.MapFrom(s => s.Subject));
Both Subject.Id and Subject are of type int. However, I get the following error:
Expression 'd => Convert(d.Subject.Id)' must resolve to top-level member and not any child object's properties. Use a custom resolver on the child type or the AfterMap option instead.Parameter name: lambdaExpression
I am using AutoMapper 2.0. Can't I solve this without AfterMap?
What is the type of ThemeNewModel.Subject? Assuming its ThemeSubject, you may have success with something like:
CreateMap<ThemeSubject, CreateThemeOrder.ThemeModel>()
.ForMember(d=>d.Id, o => o.MapFrom(s->s.Subject));
CreateMap<ThemeNewModel, CreateThemeOrder.ThemeModel>()
.ForMember(d=>d.Subject, o => o.MapFrom(s => s);
If the above does not work, you should follow the advise in the exception, and create a custom resolver.
Anyway, automapper is designed to flatten from complex types to a flat model/viewmodel types, so your ThemeNewModel is too complex, and maybe you need to rethink your design.

Resources