I am new to WCF and trying to make a simple CRUD service using Visual Studio 2012 and involving MSSQL stored procedures.
There is something I do not like about Load method. It is planned to return single entity by ID, but I have to use the .First() method because autogenerated Goods.Context.cs defines a result of GoodsLoad as ObjectResult<GoodsLoad_Result> instead of simple GoodsLoad_Result. How to make it autogenerated properly?
Goods.Context.cs (auto generated)
namespace StorehouseServer
{
public partial class storehouseEntities : DbContext
{
//.............................................
public virtual ObjectResult<GoodsLoad_Result> GoodsLoad(Nullable<int> iD)
{
var iDParameter = iD.HasValue ?
new ObjectParameter("ID", iD) :
new ObjectParameter("ID", typeof(int));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<GoodsLoad_Result>("GoodsLoad", iDParameter);
}
//.............................................
}
}
IGoods.cs
namespace StorehouseServer
{
[ServiceContract]
public interface IGoods
{
[OperationContract]
List<GoodsList_Result> List();
[OperationContract]
GoodsLoad_Result Load(int id);
}
}
Goods.svc.cs
namespace StorehouseServer
{
public class Goods : IGoods
{
public List<GoodsList_Result> List()
{
using (var db = new storehouseEntities())
{
return db.GoodsList().ToList();
}
}
public GoodsLoad_Result Load(int id)
{
using (var db = new storehouseEntities())
{
return db.GoodsLoad(id).First();
}
}
}
}
ID is an unique identifier in database and a simple select:
SELECT * FROM Goods WHERE ID=#ID;
is assumed to return a single row.
One of the fun things about EntityFramework is that you can use LINQ.
So you can do this:
db.GoodsLoad().Single(goods => goods.Id = id);
Or better yet, this:
db.GoodsLoad().Find(id);
Related
I'm trying to make a general "GET" in MONGODB.
But it does not convert error:
Cannot implicty convert type
My Service
namespace AdmissionAnonymousForm.Infrascructure.Services
{
public class BankService: IBankService
{
private readonly IMongoCollection<Bank> _bank;
public BankService(IConfiguration config)
{
var client = new MongoClient(config.GetConnectionString("AdmissionAnonymous"));
var database = client.GetDatabase("AdmissionAnonymous");
_bank = database.GetCollection<Bank>("Bank");
}
public Task<Bank> Get()
{
return _bank.Find(bank => true).ToListAsync();
}
}
}
My Model
namespace AdmissionAnonymousForm.Infrascructure.Services.Core
{
public interface IBankService
{
Task<Bank> Get();
Task<Bank> Get(Guid id);
Task<Bank> Post(Bank bank);
void Update(Guid id, Bank addressIn);
void Delete(Guid id);
}
}
the return type of Get method should be Task<List<Bank>>
public Task<List<Bank>> Get()
{
return _bank.Find(bank => true).ToListAsync();
}
You are returning a list and is expecting a single object of Bank
My Problem is the following.
I have a DataAccessLayer Project with a DalClass. In this Dal class I have many Methods for operations with Entity Framework. For example some pseudo-code to show how we do it.
class DalClass
{
public void SetEntityObject(EntityObject entityObject)
{
using (var context = new Entities())
{
context.EntityObjectSet.Attach(entityObject);
context.ChangeTracker.DetectChanges();
foreach (var entity in context.ChangeTracker.Entries())
{
entity.State = entityObject.EntityState;
}
context.SaveChanges();
}
}
public EntityObject GetEntitObject(Guid id)
{
EntityObject result;
using (var context = new Entities())
{
result = context.EntityObjectSet.Where(x => x.Id == Id);
}
return result;
}
}
Each time we do operations with EF we create a new instance context and do some work. My problem is that I have a method in my DalClass to get a List of EntityObjects Like this :
public List<EntityObject> GetEntityObjectsByIds(List<Guid> idList)
{
using (var context = new Entities())
{
var query = from entityObject in context.EntityObjectSet
where idList.Contains(entityObject.Id)
select entityObject;
return query.ToList();
}
}
After I return the List to my Business Layer class. I do some changes to each EntityObject, calculations, change some Property values and so on. After that I call a method from my BusinessLayer class to save the new edited List with this method:
public void UpdateEntityObjects(List<EntityObject> newEntityObjectList)
{
using (var context = new Entities())
{
var idList = entityObjectList.Select(x => x.Id).ToList();
var query = from entityObject in context.EntityObjectSet
where idList.Contains(entityObject.Id)
select entityObject;
var entityObjectList = query.ToList();
entityObjectList = newEntityObjectList;
context.ChangeTracker.DetectChanges();
foreach (var entity in context.ChangeTracker.Entries())
{
entity.State = EntityState.Modified;
}
context.SaveChanges();
}
}
Problem
I can not save newEntityObjectList that I Edited in my BusinessLayer. Obviously this is not working.
entityObjectList = newEntityObjectList;
So how is the best way to save the newEntityObjectList ?
Problem
I have to fier this query twice
var query = from entityObject in context.EntityObjectSet
where idList.Contains(entityObject.Id)
select entityObject;
Solution to 2. Problem could be if I use one Context instance for GetEntityObjectsByIds() and UpdateEntityObjects(). But in all our Dal Classes we avoided that. Even if I use one instance of Context class, this does not solve Problem 1. So how can I save newEntityObjectList ?
Well, my DAL class would most definetely be something like this:
class EntityObjectDAL
{
private ObjectContext/DbContext context = new ObjectContext/DbContext();
public List<EntityObject> GetObjects() { return context.EntityObjects.ToList(); }
// Tracked by context. Just change it in BL
public void SaveObjects() { context.SaveChanges(); }
// Just call SaveChanges(), no need for anything special...
public void InsertObject(EntityObject eo) { context.EntityObjects.Add(eo); }
public void UpdateObject(EntityObject eo) { context.Entry(eo).State = EntityState.Modified; }
}
Keep it simple...
im trying to stub the following line of code in C# using rhino mocks although unsuccessfully. Any suggestions please? This is the line that causes the test to fail
var header = this.repository.Headers.FirstOrDefault(h => h.Id == id);
Full details below, many thanks!
Unit test
private IRepository _repository;
[TestInitialize]
public void SetUp()
{
_repository = _mockRepository.Stub<IRepository>();
_commandService = new CoreCommandService(_repository);
}
[TestMethod]
public void MyTest()
{
// Line that doesn't work
_repository.Stub(x => x.Headers).Return(SomeThing);
}
implementation
// The Headers is stubbed although Id is null
var header = this.repository.Headers.FirstOrDefault(h => h.Id == id);
public interface IRepository
{
IEntityRepository<Header> Headers { get; }
}
UPDATE #1
public interface IEntityRepository<TEntity> : IQueryable<TEntity>, IDisposable where TEntity : class
UPDATE #2
Using the following example
var wrapper = new HeadersWrapper(...);
_repository.Stub(x => x.Headers).Return(wrapper);
Returns the following message when compiling
HeaderWrapper is not assignable to parameter type IEntityRepository<Header>
Difficult.
I think you have two options.
If you can change the return type of Headers from IEntityRepository<T> to IQueryable<T>, you can return a queryable List<T> for Headers:
IList<T> list = new List<Header> { /* Some Header object */ }
IQueryable<T> queryableList = list.AsQueryable();
_repository.Stub(x => x.Headers).Return(queryableList);
If you can't change the return type, you need to create a test fake (a new class) that derives from IEntityRepository<T>, and wraps a queryable List<T>. You will need to implement all the methods that IEntityRepository<T> and its interfaces define, but just call the relevant function on the queryable List<T>. Then you add a relevant Header to the underlying queryable List<T> as above and return a new instance of this object to stub Headers.
IQueryable<Header> Wrapper would look something like this:
public class HeadersWrapper : IQueryable<Header>
{
private readonly IQueryable<Header> _queryableSource;
public HeadersWrapper(IEnumerable<Header> source)
{
_queryableSource = source.AsQueryable();
}
public IEnumerator<Header> GetEnumerator()
{
return _queryableSource.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Expression Expression
{
get { return _queryableSource.Expression; }
}
public Type ElementType
{
get { return _queryableSource.ElementType; }
}
public IQueryProvider Provider
{
get { return _queryableSource.Provider; }
}
}
And you'd use it something like this:
var headers = new List<Header>
{
new Header { Id = "foo" }
};
var wrapper = new HeadersWrapper(headers);
repo.Stub(x => x.Headers).Return(wrapper);
And of course, you can exchange IQueryable<Header> for IEntityRepository<Header> if you want to.
so I am trying to make a generic function for a where query, not using repository
so it is possible to do something like this?
public IEnumerable<T> Something<T>(int authorId) where T : class
{
return Vmsb.Set<T>().Where(c => c.AuthorId== authorId);
}
now I can't because it dont know what c.AuthorId is
Create an interface IHaveAuthor and specify it on partial classes with this property:
public interface IHaveAuthor
{
int AuthorId { get; set; }
}
//Note that the interface is already implemented in auto-generated part.
//Or if it's Code First, just specify it directly on your classes.
public partial class Book : IHaveAuthor
{
}
public partial class Article : IHaveAuthor
{
}
Then point the interface under the generic type where constraint:
public IEnumerable<T> GetAuthorPublicationsOf<T>(int authorId)
where T : class, IHaveAuthor
{
return Vmsb.Set<T>().Where(c => c.AuthorId == authorId);
}
And the usage:
var authorBooks = query.GetAuthorPublicationsOf<Book>(authorId);
var authorArticles = query.GetAuthorPublicationsOf<Article>(authorId);
Adding on to Olexander's answer, since EF recommends you use the Unit of Work pattern, I usually don't assume a DbContext in my methods - I pass in the most generic object possible instead. Also just as a matter of style, I like to return the interface.
EDIT Updated to include Olexander's important fix to use IQueryable instead of IEnumerable.
So my method signature would look like:
public IQueryable<IHaveAuthor> Something(int authorId, IQueryable<IHaveAuthor> items)
{
return items.Where(c => c.AuthorId == authorId);
}
So calling this would be a bit different than your current calls to it - presumably something like:
var db = new MyDbContext();
var items = db.Books;
var itemForAuthor1 = Something(1, items);
Otherwise your "Something" method isn't terribly flexible - it assumes a single existing DbContext on your current object which might not be a safe assumption (since it's only supposed to live as long as this small chunk of work, whatever it is), you can't chain it with other commands, etc.
Diego hope my code helps u.
protected List<T> ListAll<T>() where T : class
{
using (MyDbContext db = new MyDbContext ())
{
return db.Set(typeof(T)).Cast<T>().AsNoTracking<T>().ToList();
}
}
protected T ListAllById<T>(int id) where T : class
{
using (MyDbContext db = new MyDbContext ())
{
return db.Set(typeof(T)).Cast<T>().Find(id);
}
}
protected void InsertObj(Object obj)
{
using (MyDbContext db = new MyDbContext())
{
db.Set(obj.GetType()).Add(obj);
db.SaveChanges();
}
}
protected void UpdateObj(Object obj)
{
try
{
using (MyDbContext db = new MyDbContext())
{
db.Set(obj.GetType()).Attach(obj);
db.Entry(obj).State = EntityState.Modified;
db.SaveChanges();
}
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show(" " + ex.Message);
}
}
protected void DeleteObj(Object obj)
{
using (MyDbContext db = new MyDbContext ())
{
db.Set(obj.GetType()).Attach(obj);
db.Entry(obj).State = EntityState.Deleted;
db.SaveChanges();
}
}
The project that I'm working on at the moment uses an IDisposable object in every method in a class. It has started getting tedious re-typing the using block at the start of every method, and was wondering if there was a way to specify a disposable variable for use in every method of the class?
public static class ResourceItemRepository
{
public static ResourceItem GetById(int id)
{
using (var db = DataContextFactory.Create<TestDataContext>())
{
// Code goes here...
}
}
public static List<ResourceItem> GetInCateogry(int catId)
{
using (var db = DataContextFactory.Create<TestDataContext>())
{
// Code goes here...
}
}
public static ResourceItem.Type GetType(int id)
{
using (var db = DataContextFactory.Create<TestDataContext>())
{
// Code goes here...
}
}
}
No, there's nothing particularly geared towards this. You could write:
public static ResourceItem GetById(int id)
{
WithDataContext(db =>
{
// Code goes here...
});
}
// Other methods here, all using WithDataContext
// Now the only method with a using statement:
private static T WithDataContext<T>(Func<TestDataContext, T> function)
{
using (var db = DataContextFactory.Create<TestDataContext>())
{
return function(db);
}
}
I'm not sure that it would be particularly beneficial though.
(Note that I've had to change it from Action<TestDataContext> in my original version to Func<TestDataContext, T> as you want to be able to return values from your methods.)
Frankly, i'd keep the verbose code, but using a snippet instead of typing it all each time.
Either create your own snippet with a special tool or use text-replacement tools like Texter
Maybe a simple refactoring is the best that you can do without resorting to something like PostSharp:
public static class ResourceItemRepository {
public static ResourceItem GetById(int id) {
using (var db = CreateDataContext()) {
// Code goes here...
}
}
public static List<ResourceItem> GetInCateogry(int catId) {
using (var db = CreateDataContext()) {
// Code goes here...
}
}
public static ResourceItem.Type GetType(int id) {
using (var db = CreateDataContext()) {
// Code goes here...
}
}
private static TestDataContext CreateDataContext() {
return DataContextFactory.Create<TestDataContext>();
}
}