linq populate custom collection - linq

I have a collection defined as:
public class MyCollection : List<MyItem>
{
...
}
public class MyItem
{
...
}
Using linq, I can use the Select method to return a IEnumerable, and I can call .ToList on that to get an IList but is there some way of getting back a type of MyCollection? Because I am tring to instantiate a class which has a property of type MyCollection, and I want to use object initialization.
For example:
public class MyClass
{
MyCollection TestCollection {get;set}
...
}
MyClass test = new MyClass()
{
...
TestCollection = SomeObject.Select(item => new MyItem()
{
...
}).ToList();
}
I get a compile error because ToList returns List and it can't cast to a MyCollection object. Is there a way to do that?

You'll need to construct your MyCollection instance with the IEnumerable<MyItem>. Add a constructor like:
public MyCollection(IEnumerable<MyItem> items) : base(items) {}
Then, when you go to use this, you can do:
TestCollection = new MyCollection(SomeObject.Select(item => new MyItem());

You could make your own extension method that builds your collection from an IEnumerable, like
public static class Extensions
{
public static MyCollection ToMyCollection(this IEnumerable<MyItem> items)
{
//build and return your collection
}
}
or if MyItem is a placeholder for generic types in your context :
public static class Extensions
{
public static MyCollection ToMyCollection<T>(this IEnumerable<T> items)
{
//build and return your collection
}
}

Just mimic ToList:
public static class MyCollectionExtensions {
public static MyCollection ToMyCollection(this IEnumerable<MyItem> source) {
if (source == null) throw new NullReferenceException();
return new MyCollection(source);
}
}
MyCollection needs a new constructor:
public class MyCollection : List<MyItem> {
public MyCollection() : base() { }
public MyCollection(IEnumerable<MyItem> source) : base(source) { }
...
}
Also, it's generally not advisable to expose a setter for a collection. You should encapsulate mutation of the collection inside the class:
public class MyClass {
public MyCollection TestCollection { get { ... } } // should return a read-only collection
public void Add(MyItem item) {
_testCollection.Add(item);
}
MyCollection _testCollection = ...;
...
}

Related

Can you create multiple instances of a class using method injection or some other form of injection?

public interface IFoo {}
public class Foo : IFoo {}
public sealed class NinjaModule : NinjectModule //Appropriately configured in project
{
public override void Load()
{
Bind<IFoo>.To<Foo>.InTransientScope();
}
}
public class SomeOtherClass : ISomeOtherInterface
{
public SomeOtherClass();
public IFoo GetFoo(IFoo foo)
{
return foo;
}
public void GetFoos()
{
foreach (var thing in everything)
{
var localFoo = GetFoo();
localFoo.UniqueProperty = "I am unique";
_fooList.Add(localFoo);
}
}
}
I need my code to look something like that.
Yes, I am fairly new to inject. I am fairly certain that I am missing a basic principle.
Thanks for any help.
I think the best approach here would be to use a factory to create the different Foo instances. And with Ninject and the Factory extension that's pretty easy.
public sealed class NinjaModule : NinjectModule //Appropriately configured in project
{
public override void Load()
{
Bind<IFoo>().To<Foo>().InTransientScope();
Bind<IFooFactory>().ToFactory();
}
}
public interface IFooFactory
{
IFoo CreateFoo();
}
public class SomeOtherClass : ISomeOtherInterface
{
private IFooFactory fooFactory;
public SomeOtherClass(IFooFactory fooFactory)
{
this.fooFactory = fooFactory;
}
public IFoo GetFoo(IFoo foo)
{
return this.fooFactory.CreateFoo();
}
public void GetFoos()
{
foreach (var thing in everything)
{
var localFoo = GetFoo();
localFoo.UniqueProperty = "I am unique";
_fooList.Add(localFoo);
}
}
}
This was a bad question. I figured out this needed to be implemented higher up by the class controlling these implementations.

ObjectContext not retrieving recent changes

This code works fine, However, if I run execute a storedprocedure in my unit of work class (or any update, delete, add operation), I'm still getting original the data. Actually, I have already a solution(posted below in controller) but Im sure this is not the most elegant way, I hope someone can help me refactor the code. please help. Thanks
My unit of work
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly ObjectContext _context;
private BookRepository _books;
public UnitOfWork(ObjectContext context)
{
if (context == null)
{
throw new ArgumentNullException("Context was not supplied");
}
_context = context;
}
public IRepository<Book> Books
{
get
{
if (_books== null)
{
_books= new BookRepository (_context);
}
return _books;
}
}
public void UpdateAuthor(int id)
{
_context.ExecuteStoreCommand("sp_UpdateAuthor #param1",
new SqlParameter("param1", id));
}
public void Commit()
{
_context.SaveChanges();
}
Book Repository
public class BookRepository : Repository<Book>
{
public BookRepository (ObjectContext context)
: base(context)
{
}
public override Machine GetById(object id)
{
return _objectSet.SingleOrDefault(s => s.Id== (int)id);
}
}
Generic Repository
public abstract class Repository<T> : IRepository<T>
where T : class, IAuditEntity
{
protected IObjectSet<T> _objectSet;
public Repository(ObjectContext context)
{
_objectSet = context.CreateObjectSet<T>();
}
public abstract T GetById(object id);
public IEnumerable<T> GetAll()
{
return _objectSet;
}
public IEnumerable<T> Query(Expression<Func<T, bool>> filter)
{
return _objectSet.Where(filter);
}
public void Add(T entity)
{
_objectSet.AddObject(entity);
}
public void Remove(T entity)
{
_objectSet.DeleteObject(entity);
}
}
Controller Code
public class HomeController : Controller
{
private IUnitOfWork _unitOfWork;
#region Core Action Methods
public HomeController()
{
this._unitOfWork = new UnitOfWork(((IObjectContextAdapter)new BookContext()).ObjectContext);
}
private IEnumerable<BookViewModel> GetBookdsViewModels(int id)
{
//THE CODE WHERE ITS NOT RETURNING THE UPDATED VLAUES
//var query = _unitOfWork.Books.GetAll().Where(d => d.Id== id);
//I WANT TO CHANGE THIS CODE
ObjectContext objectContext = ((IObjectContextAdapter)new BookContext()).ObjectContext;
ObjectSet<Book> set = objectContext.CreateObjectSet<Book>();
set.MergeOption = MergeOption.OverwriteChanges;
var query = from a in set
where a.Id== id && !a.IsDeleted
select a;
return query
.Select(
c => new BookViewModel
{
Id = c.Id ,
Name = c.Name
});
}
I believe the problem is because you're executing things directly against your database, and then trying to refer back to the local copy that's stored in your repository and they're different.
public void UpdateAuthor(int id)
{
_context.ExecuteStoreCommand("sp_UpdateAuthor #param1",
new SqlParameter("param1", id));
}
When you run this query, you're making a change in your db instead of your local - why dont you do something like this:
public void UpdateAuthor(int id)
{
var book = Books.GetById(id);
/* make changes to your book object */
_unit.Save();
}
If you're wanting to make changes using store procs, you're going to have to dispose of your context, and recreate the repo's so that you're working with data from the DB instead of the local copy.
Expanding on Mark Oreta's answer, you need to ensure your Model is updated after manually executing a stored proc on your database. If you must manually call that stored proc then try this afterward:
_context.Entry<Book>(instanceOfAuthor).Reload();
Which might be:
_context.Entry<Book>(_context.Books.GetById(id)).Reload();

Entity framework: ObjectContext and inheritance

I need to have a CRUd operations on my class (CompetenceSpecific).
Competence has three derived classes - CompetenceFunction, CompetenceArea and CompetenceSpecifc
The error I recieved:
There are no EntitySets defined for the specified entity type 'CompetencyManagement.Domain.Entities.CompetenceFunction'. If 'CompetencyManagement.Domain.Entities.CompetenceFunction' is a derived type, use the base type instead. Parameter name: TEntity
How should I correct this? Please suggest a solution that would solve my problem. Thanks
Please check the code below, I removed some parts of the code for simplicity.
--MODEL
public class Competence
{
public int CompetenceID { get; set; }
public int CourseID { get; set; }
...
}
public class CompetenceFunction : Competence
{
}
--REPOSITORY and interfaces
public interface IRepository<T> where T : class
{
T GetById(object id);
IEnumerable<T> GetAll();
IEnumerable<T> Query(Expression<Func<T, bool>> filter);
void Add(T entity);
void Remove(T entity);
}
public abstract class Repository<T> : IRepository<T>
where T : class
{
protected IObjectSet<T> _objectSet;
public Repository(ObjectContext context)
{
_objectSet = context.CreateObjectSet<T>();
}
...
}
public class CompetenceFunctionRepository : Repository<CompetenceFunction>
{
public CompetenceFunctionRepository(ObjectContext context)
: base(context)
{
}
public override CompetenceFunction GetById(object id)
{
return _objectSet.SingleOrDefault(s => s.CompetenceID == (int)id);
}
}
--UNIT oF WORK
public interface IUnitOfWork
{
IRepository<CompetenceFunction> CompetenceFunctions { get; }
IRepository<CompetenceArea> CompetenceAreas { get; }
IRepository<CompetenceSpecific> CompetenceSpecifics { get; }
void Commit();
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private CompetenceFunctionRepository _competencefunction;
private CompetenceAreaRepository _competencearea;
private CompetenceSpecificRepository _competencespecifc;
public UnitOfWork(ObjectContext context)
{
if (context == null)
{
throw new ArgumentNullException("Context was not supplied");
}
_context = context;
}
#region IUnitOfWork Members
public IRepository<CompetenceFunction> CompetenceFunctions
{
get
{
if (_competencefunction == null)
{
_competencefunction = new CompetenceFunctionRepository(_context);
}
return _competencefunction;
}
}
public IRepository<CompetenceArea> CompetenceAreas
{
get
{
if (_competencearea == null)
{
_competencearea = new CompetenceAreaRepository(_context);
}
return _competencearea;
}
}
public IRepository<CompetenceSpecific> CompetenceSpecifics
{
get
{
if (_competencespecifc == null)
{
_competencespecifc = new CompetenceSpecificRepository(_context);
}
return _competencespecifc;
}
}
--Im getting an error in this part of Repository
public Repository(ObjectContext context)
{
_objectSet = context.CreateObjectSet<T>();
}
There are no EntitySets defined for the specified entity type 'CompetencyManagement.Domain.Entities.CompetenceFunction'. If 'CompetencyManagement.Domain.Entities.CompetenceFunction' is a derived type, use the base type instead. Parameter name: TEntity
Here's how I implement in the controller
private IUnitOfWork _unitOfWork;
var a = _unitOfWork.CompetenceFunctions.GetAll();
return View(a);
You have to get derived type by the OfType function, e.g.
context.CreateObjectSet<Competence>().OfType<CompetenceFunction>()
In your case that would mean that there is only a CompetenceRepository that serves all derivatives of Competence.
Edit
(After your comment)
First, UoW is meant for temporarily storing changes that should be dealt with in one batch (like changes to be committed to the database). GetAll and similar functions are repository stuff.
But do you need repositories? I like this post. When beginning to know EF, I would focus on the ins and outs of EF without getting distracted too much by surrounding architecture. E.g. start with services that at the inside communicate directly with the context and expose methods like GetCompetenceFunctions, GetCompetenceAreas (using OfType), and SaveCompetenceFunction, ....
You can address these service methods directly from action methods in the MVC controllers.

Repository Pattern and Azure Table Storage(???)

While doing the following simple example, I found the following difficulties
As the title says, I am intending to use the Repository pattern while I am storing data in the Azure table storage.now I have couple of classes, Repository.cs, IRepository.cs, DataContext.cs and the Controller.
During my reading I found some info and been doing as follows.
IRepository.cs
public interface IRepository<T> where T: TableServiceEntity
{
T GetById(int Id);
IQueryable<T> GetAll();
}
and the DataContext.cs
public class DataContext<T>:TableServiceContext where T:TableServiceEntity
{
public DataContext(CloudStorageAccount storageaccount, StorageCredentials credentials)
: base(storageaccount.TableEndpoint.AbsoluteUri, credentials)
{
// _storageAccount = storageaccount;
var storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(KEY_STORAGE));
storageAccount.CreateCloudTableClient().CreateTableIfNotExist(tableName);
}
public IQueryable<T> DeviceTable
{
get { return CreateQuery<T>(tableName); }
}
}
plus some part of the controller(I have already data in the table which I created before)
public class DeviceMeController : Controller
{
private IRepository<Entity>_repository;
public Controller() : this(new Repository<Entity>())
{
}
public Controller(IRepository<Entity> repository)
{
_repository = repository;
}
public ActionResult Index()
{
var List = _repository.GetAll();
return View(deviceList);
}
and the the Implementation of the interface Reposistory.cs, here is where I have an error and got lost somewhere
public class Repository<T>:IRepository<T> where T:TableServiceEntity
{
private DataContext<T> _serviceContext;
// here get tablename as pararameter;
// so the Enities call this function
public Repository()
{
// the same context for multiple tables ?
}
// perhaps it should take the table Name
public void Add(T item)
{
_serviceContext.AddObject(TableName,item);
_serviceContext.SaveChangesWithRetries();
}
public IQueryable<T> GetAll()
{
var results = from c in _serviceContext.Table
select c;
return results;
Error is about the null reference, the debugger shows the variable results is null?
In the end I need to know few things.
what should I do in the Repository.cs constructor? I believe the Datacontext.cs class has to be in a separate class ...
any Hint here
Hy,
first of all I presume you left out some code, because I don't see how you get your context in your repository. But supposing you do set it correctly, (injection?) taking into account the way you desinged your datacontext the repository doesn't need to know the table name because it is set in the following lines of code:
public IQueryable<T> DeviceTable
{
get { return CreateQuery<T>(Constants.DeviceTableName); }
}
So when you create a query based on the IQueryable DeviceTable, the table name is already set.
The thing is I don't see the need for your context class, especially as it can only bring over a single entity type (it is generic and based on an entity).
A basic layout of my Repository for Azure Table Storage is:
public abstract class CloudRepository<TEntity> : ICloudRepository<TEntity>
{
private TableServiceContext _tableServiceContext;
private string _tableName;
public string TableName
{
get { return _tableName ?? ( _tableName = typeof(TEntity).Name.Replace("Entity", string.Empty).ToLower()); }
}
public CloudStorageAccount StorageAccount
{
get
{
return CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));
}
}
public CloudTableClient TableClient
{
get
{
CloudTableClient cloudTableClient = StorageAccount.CreateCloudTableClient();
cloudTableClient.CreateTableIfNotExist(TableName);
return cloudTableClient;
}
}
public TableServiceContext ServiceContext
{
get
{
return _tableServiceContext ?? (_tableServiceContext = TableClient.GetDataServiceContext());
}
}
public IEnumerable<TEntity> FindAll()
{
return ServiceContext.CreateQuery<TEntity>(TableName).ToList();
}
}
Hope this helps you.

How to test Singleton class that has a static dependency

I have a Singleton class that uses the thread-safe Singleton pattern from Jon Skeet as seen in the TekPub video. The class represents a cached list of reference data for dropdowns in an MVC 3 UI.
To get the list data the class calls a static method on a static class in my DAL.
Now I'm moving into testing an I want to implement an interface on my DAL class but obviously cannot because it is static and has only one static method so there's no interface to create. So I want to remove the static implementation so I can do the interface.
By doing so I can't call the method statically from the reference class and because the reference class is a singleton with a private ctor I can't inject the interface. How do I get around this? How do I get my interface into the reference class so that I can have DI and I can successfully test it with a mock?
Here is my DAL class in current form
public static class ListItemRepository {
public static List<ReferenceDTO> All() {
List<ReferenceDTO> fullList;
... /// populate list
return fullList;
}
}
This is what I want it to look like
public interface IListItemRepository {
List<ReferenceDTO> All();
}
public class ListItemRepository : IListItemRepository {
public List<ReferenceDTO> All() {
List<ReferenceDTO> fullList;
... /// populate list
return fullList;
}
}
And here is my singleton reference class, the call to the static method is in the CheckRefresh call
public sealed class ListItemReference {
private static readonly Lazy<ListItemReference> instance =
new Lazy<ListItemReference>(() => new ListItemReference(), true);
private const int RefreshInterval = 60;
private List<ReferenceDTO> cache;
private DateTime nextRefreshDate = DateTime.MinValue;
public static ListItemReference Instance {
get { return instance.Value; }
}
public List<SelectListDTO> SelectList {
get {
var lst = GetSelectList();
lst = ReferenceHelper.AddDefaultItemToList(lst);
return lst;
}
}
private ListItemReference() { }
public ReferenceDTO GetByID(int id) {
CheckRefresh();
return cache.Find(item => item.ID == id);
}
public void InvalidateCache() {
nextRefreshDate = DateTime.MinValue;
}
private List<SelectListDTO> GetSelectList() {
CheckRefresh();
var lst = new List<SelectListDTO>(cache.Count + 1);
cache.ForEach(item => lst.Add(new SelectListDTO { ID = item.ID, Name = item.Name }));
return lst;
}
private void CheckRefresh() {
if (DateTime.Now <= nextRefreshDate) return;
cache = ListItemRepository.All(); // Here is the call to the static class method
nextRefreshDate = DateTime.Now.AddSeconds(RefreshInterval);
}
}
}
You can use the singleton based on instance(not based on static), for which you can declare interface like this.
public interface IListItemRepository
{
List<ReferenceDTO> All();
}
public class ListItemRepository : IListItemRepository
{
static IListItemRepository _current = new ListItemRepository();
public static IListItemRepository Current
{
get { return _current; }
}
public static void SetCurrent(IListItemRepository listItemRepository)
{
_current = listItemRepository;
}
public List<ReferenceDTO> All()
{
.....
}
}
Now, you can mock IListItemRepository to test.
public void Test()
{
//arrange
//If Moq framework is used,
var expected = new List<ReferneceDTO>{new ReferneceDTO()};
var mock = new Mock<IListItemRepository>();
mock.Setup(x=>x.All()).Returns(expected);
ListItemRepository.SetCurrent(mock.Object);
//act
var result = ListItemRepository.Current.All();
//Assert
Assert.IsSame(expected, result);
}
Which DI framework are you using? Depending on your answer, IOC container should be able to handle single-instancing so that you don't have to implement your own singleton pattern in the caching class. In your code you would treat everything as instanced classes, but in your DI framework mappings you would be able to specify that only one instance of the cache class should ever be created.
One way to test it would be if you refactor your ListItemReference by adding extra property:
public sealed class ListItemReference {
...
public Func<List<ReferenceDTO>> References = () => ListItemRepository.All();
...
private void CheckRefresh() {
if (DateTime.Now <= nextRefreshDate) return;
cache = References();
nextRefreshDate = DateTime.Now.AddSeconds(RefreshInterval);
}
}
And then in your test you could do:
ListItemReference listReferences = new ListItemReference();
listReferences.References = () => new List<ReferenceDTO>(); //here you can return any mock data
Of course it's just temporary solution and I would recommend getting rid of statics by using IoC/DI.

Resources