Building application with Entity framework dbContext API issues - wcf

I am developing a WCF Service application. It is going to be a part of large system. It provides some business logic and is based on Entity framework 4.1. I want to divide application code into 2 tiers (projects in VS, dll's): Service (which contains business logic) and DAL.
I have such database model in my project
ClassModel
classID : int, PK
classIdentity : string
teacherName : string
statisticInfo : int
isRegistered : bool
StudentModel
studentID : int, PK
studentIdentity : string
classID : int, FK
For this I am generating code using dbContext templates and I get:
public partial class ClassModel
{
public ClassModel()
{
this.Student = new HashSet<StudentModel>();
}
public int ClassID { get; set; }
public string ClassIdentity { get; set; }
public string TeacherName { get; set; }
public int StatisticInfo { get; set; }
public bool IsRegistered { get; set; }
public virtual ICollection<TerminalModel> Terminal { get; set; }
}
public partial class StudentModel
{
public int StudentID { get; set; }
public string StudentIdentity { get; set; }
public bool IsRegistered { get; set; }
public virtual ClassModel Class { get; set; }
}
I want to expose only some of this information through the service, so I have different model as a data contract:
[DataContract]
public class Clas{
[DataMember]
public string ClassIdentity {get;set;}
[DataMember]
public string TeacherName {get;set;}
[DataMember]
public string ClassMark {get;set;} //computed from statisticInfo
[DataMember]
public int NumberOfStudents {get;set;} //amount of students in this class
}
And my part of my ServiceContract:
[OperationContract]
public void RegsterClass(Clas clas); //(if given clas does not exists adds it and) sets its isRegistered column to True
[OperationContract]
public Clas GetClass(string classIdentity);
As you can see some fields are not present, others are being computed.
In such case I have some concerns about how should I built application properly. Could you write example code which implements the interface methods using everything I mentioned in the way that you think is proper?

Try using T4 templates
It is possible to use T4 templates to generate the dbContext classes, the data transfer objecs (more on that later), the interface as well as all the two methods you have there for each entity in your model: RegsterClass and GetClass. (this would translate to RegsterStudent, GetStudent, and so on for every entity)
Then you can use AutoMapper on NuGet to map from Clas to ClassModel.
I've implemented something similar. I don't pass any of my dbcontext based entities across the wire. I use Data transfer objects for each entity. So a Toyota entity, has a ToyotaDto that has the data annotations and is used for all the WCF CRUD operations. When "Getting" a toyotaDto, I map Toyota to ToyotaDto and return the Dto, when saving, I map the Dto to an entity, of course deleting is done by key, so no Dto necessary.
There are several(1) good(2) examples(3) online you can modify to suit, and if you want I can paste in some of the templates I'm using.

Related

Designing a hierarchy of abstract classes and using it in EF Core

I am using .NET Core with Entity Framework Core to build a finance app and I want to know how to make my design better.
I have a 1 to Many relationship between two entities, BankAccount and Transaction. In a way that:
1 Account can have many Transactions
1 Transaction Belongs to 1 Account
However, I want to include bank accounts and transactions coming from different 3P sources. And while this relationship and the main fields are common across different sources, each source has a unique set of properties I want to keep.
To achieve this I decided to define these entities as abstract classes. This way, you can only instantiate concrete versions of these entities, each coming from a particular data source.
public abstract class Transaction : BaseEntity
{
public DataSource Source { get; private set; }
public decimal Amount { get; private set; }
public DateTime Date { get; private set; }
public string Name { get; private set; }
public BankAccount BankAccount { get; private set; }
public Guid BankAccountId { get; private set; }
...
}
public abstract class BankAccount : BaseEntity
{
public DataSource Source { get; private set; }
public string Name { get; private set; }
public Balance Balance { get; private set; }
public IEnumerable<Transaction> Transactions {get; private set;}
...
}
Here is a trimmed down example of the concrete implementations:
public class PlaidTransaction : Transaction
{
public string PlaidId { get; private set; }
private PlaidTransaction() : base() { }
public PlaidTransaction(decimal amount, DateTime date, string name, Guid bankAccountId, string plaidId) : base( amount, date, name, bankAccountId)
{
PlaidId = plaidId;
}
}
public class PlaidBankAccount : BankAccount
{
public string PlaidId { get; private set; }
...
}
I am using .Net Core with Entity Framework Core to persist my data and I managed to store my concrete classes all in the same table (TPH approach)
This works great and now all my entities live under the same table. So I can either query all Transactions or those of a certain type using LINQ's OfType<T> extension.
DbSet<Transaction> entities = _context.Set<Transaction>();
IEnumerable<PlaidTransaction> plaidTransactions = entities.OfType<PlaidTransaction>();
However, when I access my BankAccount field from my concrete Transaction I don't get the concrete instance. So something like this doesn't work.
plaidTransactions.Where((t) => t.BankAccount.PlaidId)
Instead I have to cast it:
plaidTransactions.Where((t) => (t.BankAccount as PlaidBankAccount).PlaidId)
What can I do to avoid casting everywhere? I feel there's a missing piece in my design that would make all my code easier. I was thinking of overriding the getters on my concrete classes but I don't know if I can return a derived class to a base class method. Maybe I should move to generics but 1) I still want to keep the fixed relationship between these entities and 2) how would EF Core handle this?

Data Contract for Two database Tables during Join Condition

I have 2 tables in my DB like Patient Table and Appointment Table
for which I have created 2 Data Contracts namely Patient,Appointment in my WCFREST Service.
I use List<Patient> to fill the DB Table info in the List object and
List<Appointment> to fill the DB Table info in List obj as well.
Here I have an Operation Contract which returns data from 2 tables using Join Statement
For that how should I store the result, because I have 2 different objects ?
Do I need to create one more DataContract by combining fields of these two tables?
Use Entity frame work (table first or model first approach). But as you already have tables available you might want to base your model on the tables. Whatever way you choose ultimately your Data Contract should look as below:
[DataContract]
public class Patient
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Appointment> Appointments { get; set; }
}
[DataContract]
public class Appointment
{
[DataMember]
public int ID { get; set; }
[DataMember]
public DateTime AppointmentTime { get; set; }
[DataMember]
public Address Venue { get; set; }
}
Trick is to make DataContract for each of table. You don't have to create multiple data contracts to match your needs.
The service contract should be as below:
[ServiceContract]
public interface IPatientService
{
[OperationContract]
List<Patient> GetAllPatients();
}
you can then use the DbContext provided by the EF in combination with extensions (Dependency injection) as below. Or just get rid of the constructor if you don't want to go advanced with it and create _context object right on intialization. Here is a sample.
public class PatientService : IPatientService
{
HospitalDbContext _context;
public PatientService(HospitalDbContext _context)
{
this._context = _context;
}
public List<Patient> GetAllPatients()
{
return (from patient in _context.Patients
select patient).ToList<Patient>();
}
}
You are free to add LINQ conditions here to take joins and other operations as well.
[DataContract]
class A
{
[DataMember]
public string PatientName { get; set; }
// more stuff.
}
[DataContract]
class B
{
[DataMember]
public string HospitalName { get; set; }
// more stuff.
}
[DataContract]
class C
{
[DataMember]
public A prop1 { get; set; }
[DataMember]
public B prop2 { get; set; }
// more stuff.
}

How to ignore a DataMember from the superclass in a subclass

The title is pretty self-explanatory.
I have a base WCF DataContract, let's call it the PersonContract, which covers all fields of the Person entity in my database.
I have a number of client applications that call the same service through endpoints of different interfaces implemented by that service. This is because (amongst other differences) I want every of those applications to be able to access and edit only a specific subset of the Person entity.
Now if I want to define a contract with all the properties of PersonContract except one, can I subclass PersonContract and ignore a single property in the subclass?
Or is my only option building contracts from the smallest subset (but I doubt I can fully avoid repeating code then)?
Out of curiosity I did a couple tests and it doesn't look like it'll work.
Here are the data contracts I used:
[DataContract]
public class Person
{
[DataMember]
public virtual string FirstName { get; set; }
[DataMember]
public virtual string MidName { get; set; }
[DataMember]
public virtual string LastName { get; set; }
}
[DataContract]
public class Person2 : Person
{
[IgnoreDataMember]
public override string MidName { get; set; }
}
And my service contract:
public interface IService1
{
[OperationContract]
Person GetPerson();
[OperationContract]
Person2 GetPerson2();
}
Both operations return the same result.
Another way that you might be able to produce the results you're looking for could be to define your minimal contract (the one with missing the excluded properties) and inherit from it adding the field needed by the other operation.
The equivalent data contracts would look something like:
[DataContract]
public class Person2 : Person
{
[DataMember]
public virtual string MidName { get; set; }
}
[DataContract]
public class Person
{
[DataMember]
public virtual string FirstName { get; set; }
[DataMember]
public virtual string LastName { get; set; }
}
And I've verified that the results are as I would expect.

How to cast Entity framework Objects in Web API?

I'm using entity framework and I figured out that it ain't able to serialize the output of
EDM Objects. For now I'm using Northwind Products-table. SO thereforth I'm forced to cast the Object to another and are using the .Cast but it doesn't work.
The only solution I have is to property by property do it manually in my code, but I'm thinking - there must be a better way!
For god's sake - it is 2013! And this Entity seems like a good idea in the beginning but it has so many gotchas and constraints that it actually hinders more than it helps, but anyway the EDMX diagrams are nice!
Anybody who has a better solution to casting the objects?
POCO
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
//public Nullable<int> SupplierID { get; set; }
//public Nullable<int> CategoryID { get; set; }
public string QuantityPerUnit { get; set; }
public Nullable<decimal> UnitPrice { get; set; }
public Nullable<short> UnitsInStock { get; set; }
public Nullable<short> UnitsOnOrder { get; set; }
public Nullable<short> ReorderLevel { get; set; }
//public bool Discontinued { get; set; }
public Category Category { get; set; }
//public ICollection<Order_Detail> Order_Details { get; set; }
//public Supplier Supplier { get; set; }
}
View Model
public class ProductsViewModel
{
public List<POCO.Product> Products { get; set; }
public ProductsViewModel()
{
using (NorthwindEntities dNorthwindEntities = new NorthwindEntities())
{
this.Products = dNorthwindEntities.Products.Cast<POCO.Product>().ToList();
Web api controller:
public class ProductsController : ApiController
{
public List<Product> GetAllProducts()
{
var viewmodel = new ProductsViewModel();
return viewmodel.Products;
}
1.
You can use frameworks like AutoMapper to handle Entities to ViewModel / DTO mapping automatically.
2.
Using Entities in the View (even in their POCO form) is not recommended for couple of reasons:
Security: Sending entities back to the client/view may expose more data than you intended.
Serialization: Since your entities usually contain reference to another entities and those entities may contain a reference back to the (parent) entity, you have to configure your serializer to handle this situation otherwise you'll get Circular Dependency Exception.
Incompatibility: The structure of your entity may not be compatible with what your view/client needs to render itself. Sometimes your view just needs a simple string while the entity holds this data in a much complex way hence the view needs to 'extract' it and you end up with a view full of unnecessary entity-drill-down code.

EF4 Code Only - Map Columns to Property Complex type

I have a table like this:
Name
Tree
Iron
Clay
Added
I want to map it to a model like this:
Name
Resources
Tree
Iron
Clay
Added
In makes sense to map it like this, when working with it in my program, but doing it that way in the databse would just make it more complex ... not would not add any useful things.
Is it possible with EF4 Code ONly?
public class Sample
{
public int Id { get; set;} // primary key required
public string Name {get;set;}
public DateTime Added{get;set;}
}
public class Resource
{
// no Id defined here
public string Tree{get;set;}
public string Iron { get;set;}
public string Clay { get;set;}
}
public class SampleDB : DbContext
{
//public DbSet<Resource> Resources { get; set; } // should not be there
public DbSet<Sample> Samples { get; set; }
}