I am developing a Web Services application, and when I get from my EF model - for example a list of my "User" object - I get the fields of my table PLUS the Foreign Keys, etc?
Does any know how to avoid these? I have been trying to modify the poco template but without luck.
namespace JOhn.DataAccess
{
[Serializable()]
[DataContract(Namespace = "")]
public class CustomEntityObject : EntityObject
{
//[DataMember]
[Browsable(false)]
[XmlIgnore]
[SoapIgnore]
public new EntityKey EntityKey { get; set; }
}
}
A common solution is to use the DTO ("Data Transfer Object") pattern.
Define a new class called UserDto which contains just the fields you want to expose over your API, then copy the values from your User entity object to a UserDto instance.
Packages like AutoMapper can be used to avoid writing the value copying code.
There is a
[ScriptIgnore]
Attribute as well, it works well with Microsoft's default JavaScript Serializer.
namespace AutoFX.DataAccess
{
[Serializable()]
[DataContract(Namespace = "")]
public class CustomEntityObject : EntityObject
{
//[DataMember]
[Browsable(false)]
[XmlIgnore]
[SoapIgnore]
[ScriptIgnore]
public new EntityKey EntityKey { get; set; }
}
}
try creating a model class and bind the data of the user object using this model. This will help to overcome the dependencies ..
Another way to do it without creating DTO's is to use JSON.Net in your MVC Application. Then your object could look like:
namespace John.DataAccess
{
[Serializable()]
[DataContract(Namespace = "")]
public class CustomEntityObject : EntityObject
{
//[DataMember]
[Browsable(false)]
[XmlIgnore]
[SoapIgnore]
[JsonIgnore]
public new EntityKey EntityKey { get; set; }
}
}
Related
I do a Generic and using DI
so I create a empty class
public class DBRepo
{
}
and my model class to inheriting class DBRepo
public partial class UserAccount : DBRepo
{
public int Id { get; set; }
public string Account { get; set; }
public string Pwd { get; set; }
}
then this is a Interface to do CRUD
public interface IDBAction<TEntity> where TEntity : class,new()
{
void UpdateData(TEntity _entity);
void GetAllData(TEntity _entity);
}
public class DBService<TEntity> : IDBAction<TEntity> where TEntity : class,new()
{
private readonly CoreContext _db;
public DBService(CoreContext _db)
{
this._db = _db;
}
public void UpdateData(TEntity _entity)
{
this._db.Set<TEntity>().UpdateRange(_entity);
this._db.SaveChanges();
}
public void GetAllData(TEntity _entity)
{
var x = this._db.Set<TEntity>().Select(o => o).ToList();
}
}
And I Dependency Injection Service Provider in constructor
this.DBProvider = new ServiceCollection()
.AddScoped<IDBAction<DBRepo>, DBService<DBRepo>>()
.AddScoped<DBContext>()
.AddDbContext<CoreContext>(options => options.UseSqlServer(ConnectionString))
.BuildServiceProvider();
last step I Get Services
DBProvider.GetService<IDBAction<DBRepo>>().GetAllData(new UserAccount());
I will get a error message same with title
or I change to
DBProvider.GetService<IDBAction<UserAccount>>().GetAllData(new UserAccount());
I'll get other message
Object reference not set to an instance of an object.'
but the void UpdateData() is can work,
so how to fix GetAllData() problem?
The error simply is because the class you're using here UserAccount has apparently not been added to your context, CoreContext. There should be a property there like:
public DbSet<UserAccount> UserAccounts { get; set; }
Regardless of whether you end up using the generic Set<T> accessor, you still must defined a DbSet for the entity on your context.
That said, you should absolutely not be creating your own service collection inside your repo. Register your context and your repo with the main service collection in Startup.cs and then simply inject your repo where you need it. The DI framework will take care of instantiating it with your context, as long as you have a constructor that takes your context (which you seem to).
And that said, you should ditch the repo entirely. It still requires a dependency on Entity Framework and doesn't do anything but proxy to Entity Framework methods. This is just an extra thing you have to maintain and test with no added benefit.
I am started with my first Dapper Dal project.
I have three projects:
- Website (MVC)
- DataLayer (Dapper)
- Model (Poco Classes)
I want to add validation to my model but i also want to use clean poco classes for my datalayer. My datalayer use dapper to map my poco classes to the database.
I have searched the internet but i can't find a good answer.
My question is:
Where do i add my validation?
- In a seppetated project with classes that extend my poco classes or is there a different way?
If you want a clean separation between your DAL classes and your MVC classes, then you can do just that by, for instance, using ViewModels in your MVC-project. The ViewModel would have the properties and validations that works best with what you are presenting in the browser. Your controller would be responsible for mapping the data between the DAL classes and the ViewModels. Automapper is a very good tool for just that.
It would look a bit like the following:
DAL:
public class MyDapperClass
{
public int Id { get; set; }
public string SomeProperty { get; set; }
}
ViewModel:
public class MyViewModelClass
{
public int Id { get; set; }
[StringLength(50),Required]
public string SomeProperty { get; set; }
}
Controller:
// using AutoMapper;
public class MyController : Controller
{
public MyController()
{
// Set up AutoMapper to be able to map your class
Mapper.CreateMap<MyDapperClass, MyViewModelClass>();
}
public ActionResult MyAction()
{
var dalObject = DAL.GetObject();
var viewModel = Mapper.Map<MyViewModelClass>(dalObject);
return View(viewModel);
}
}
I'm testing the new ApiController in asp.net mvc 4 beta but when I try to return an class that looks like the following only a few properties gets serialized?
public class PageModel : IPageModel {
public string Id { get; set; }
public virtual IPageMetadata Metadata { get; private set; }
public PageModel() {
Metadata = new PageMetadata();
}
}
this is the code in my api controller
// GET /api/pages/5
public PageModel Get(string id) {
return new PageModel { Id = "pages/1", Metadata = {Name = "Foo"} };
}
and this is the result
{
Id: "pages/1",
Parent: null
}
Is it possible to get the complete object and not only a few things?
Readonly properties are not serialized. Make the setter of the Metadata property public if you want it to be serialized. I think that this behavior is normal for input parameters but not for output which is your case. IMHO it's a bug that could be workarounded by using a JSON serializer which supports this but maybe they will fix it before the final release and allow readonly properties to be serialized for output parameters.
Actually it's not a big pain, because you should be using view models anyway, so simply map your domain model to a view model and have your method return this view model which will contain only the properties that you need to actually expose to the client. This view model will contain properties with public getters and setters.
I have a problem with serialization composite class (using WCF Service).
here my class in namespace1 (it is not in service namespace) :
[DataContract]
public class UpData
{
[DataMember]
public double Version ;
public UpData()
{
this.Version = -1;
}
}
In my Service namespace (in interface) I deŃlare this procedure :
ArrayList GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
ArrayList contains UpData objects.
I have error(
How will be right to send ArrayList of UpData objects? (may be specific DataContract?)
Thanks a lot!
I'm not sure if ArrayList is serializable by default. Using a generic list could solve your problem:
[OperationContract]
List<UpData> GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
EDIT: I think you also need to specify a getter and setter for your Version property, i.e.
[DataContract]
public class UpData
{
[DataMember]
public double Version { get; set; }
public UpData()
{
this.Version = -1;
}
}
More info here.
With FluentNHibernate I have mapped a UserPreference entity which references the GeneralPreference, GeneralPreferenceOption, and Profile entities:
public class UserPreference
{
public virtual long Id { get; set; }
public virtual Profile Profile { get; set; }
public virtual GeneralPreference Preference { get; set; }
public virtual GeneralPreferenceOption Value { get; set; }
}
It's easy enough to map a list of UserPreference on my Profile entity, but what I actually would like to do is wrap this list inside another class so that I can simplify operations concerning a user's given preferences:
public class Preferences
{
public IList<UserPreferences> UserPreferences{get;set;}
public Language Language {
{
//look up the language preference here
}
}
This kind of feels like a Component, but Components were not created for this type of scenario. Does anyone have any pointers on how I might map this?
I figured out a way to do this by mapping a private property on my Profile Entity. Using the techniques from the Fluent NHibernate wiki on mapping private properties (http://wiki.fluentnhibernate.org/Fluent_mapping_private_properties) I map a collection of UserPreference on my Profile Entity. Then I create another class PropertyHandler which takes an IEnumerable as a constructor parameter and make an instance of this a public property on Profile as well:
public class Profile
{
private PreferenceHandler _preferenceHandler;
get { return _preferenceHandler ?? (_preferenceHandler = new PreferenceHandler(UserPreferences)); }
private IEnumerable<UserPreference> UserPreferences { get; set; }
public static class Expressions
{
public static readonly Expression<Func<Profile, IEnumerable<UserPreference>>> UserPreferences = x => x.UserPreferences;
}
}
Notice the nested static class. It's used to enable mapping of a private property with FluentNHibernate.
The mapping class looks something like this:
public class ProfileMappings : ClassMap<Profile>
{
public ProfileMappings()
{
//... other mappings
HasMany(Profile.Expressions.UserPreferences);
}
}
I can now use the PreferenceHandler class to create helper methods over my collection of UserPreference.
An alternative is to build extension methods for IEnumberable. This works, but I decided not to do this because
1) I'm not really extending the IEnumerable functionality and
2) my helper methods disappear inamongst all the other IEnumerable extension methods making the whole thing a bit cluttered.