Linq to SQL Cannot attach an entity that already exists - linq

I am getting a error Cannot attach an entity that already exists. at the line DbSet.Attach(entity); . Is there something I need to do different before the update?
Should I add a if condition to the ‘DbSet.Attach‘?
Error
System.Data.Linq.Table1.Attach(TEntity entity, Boolean asModified) at System.Data.Linq.Table1.Attach(TEntity entity)
public void ResetAdminConfig(AdminConfig _adminConfig)
{
AdminConfig adminConfig = new AdminConfig();
adminConfig = GetAdminConfig().SingleOrDefault(e => e.Id == _adminConfig.Id);
adminConfig.ConfigSetting = false;
adminConfig.Modified = DateTime.Now;
UnitOfWork.GetRepository<AdminConfig>().Update(adminConfig);
}
public void Update(TEntity entity)
{
DbSet.Attach(entity);
_context.Refresh(RefreshMode.KeepCurrentValues, entity);
}
public IRepository<TEntity, OrderTemplateDataContext> GetRepository<TEntity>() where TEntity : class
{
if (!_repositories.ContainsKey(typeof(TEntity)))
{
var repository = new OrderTemplateRepository<TEntity>(Context);
_repositories.Add(typeof(TEntity), repository);
}
return (IRepository<TEntity, OrderTemplateDataContext>)_repositories[typeof(TEntity)];
}
private AdminConfig GetAdminConfig(long id)
{
return GetAdminConfigs().SingleOrDefault(e => e.Id == id);
}
private IQueryable<AdminConfig> GetAdminConfigs()
{
return UnitOfWork.GetRepository<AdminConfig>().Get(e => !e.IsDeleted);
}

Related

Database handler globally as Singleton pattern in xamarin forms

I am developing an application which have a local database for offline support. So I am using Sqlite.net.pcl plugin and its working fine for all Create, Insert, Update and Delete table for every class model.
But instead of creating a separate database activities like insert, get, update for each Model class, I tried to worked on singeton pattern of common database handler(DatabasHandler.cs).
This is my code which I tried to workout singleton pattern,
public void CreateTable<T>() where T : new()
{
var myClass = new T();
myDatabase.CreateTableAsync<T>().Wait();
}
I called this function from my EmployeeViewModel class like this;
App.Database.CreateTable<EmployeeModel>();
here EmployeeModel is a model class and its worked fine, also the above function is successfully created a Employee Table. Doing the same way I created rest of the Tables from each ViewModel like this;
App.Database.CreateTable<SalaryModel>(); // call from SalaryViewModel Page
App.Database.CreateTable<EmployeeAttendanceModel>(); // call from AttendanceViewModel Page
Next: So how can I insert and get all list items into DatabaseHandler.cs using same (Create Table)singleton pattern. My question is;
How should I create a method for Insert/Get/Update a list in DatabaseHandler.cs(Singleton class)?
How should I call those method(Insert/Get/Update) from its viewmodel?
Please help me,
Now I had a similar thing in my Old XF app this is how I implemented the Singleton this will also answer your first question:
How should I create a method for Insert/Get/Update a list in DatabaseHandler.cs(Singleton class)?
public class DatabaseHandler: IDisposable
{
private SQLiteConnection conn;
//public static string sqlpath;
private bool disposed = false;
private static readonly Lazy<DatabaseHandler> database = new Lazy<DatabaseHandler>(() => new DatabaseHandler());
private DatabaseHandler() { }
public static DatabaseHandler Database
{
get
{
return database.Value;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
Dispose();
}
disposed = true;
}
public bool InitDatabase()
{
var ifExist = true;
try
{
this.CreateDatabase();
ifExist = TableExists(nameof(LocationModel), conn);
if (!ifExist)
this.CreateTable<LocationModel>();
return true;
}
catch (Exception ex)
{
return false;
}
}
public static bool TableExists(String tableName, SQLiteConnection connection)
{
var cmd = connection.CreateCommand("SELECT name FROM sqlite_master WHERE type = 'table' AND name = #name", new object[] { tableName });
//cmd.CommandText = "SELECT * FROM sqlite_master WHERE type = 'table' AND name = #name";
//cmd.Parameters.Add("#name", DbType.String).Value = tableName;
string tabledata = cmd.ExecuteScalar<string>();
return (cmd.ExecuteScalar<string>() != null);
}
public SQLiteConnection GetConnection()
{
var sqliteFilename = "xamdblocal.db3";
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
var path = Path.Combine(documentsPath, sqliteFilename);
Console.WriteLine(path);
if (!File.Exists(path)) File.Create(path);
//var plat = new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid();
var conn = new SQLiteConnection(path);
// Return the database connection
return conn;
}
private bool CreateDatabase()
{
conn = GetConnection();
string str = conn.DatabasePath;
return true;
}
public bool CreateTable<T>()
where T : new()
{
conn.DropTable<T>();
conn.CreateTable<T>();
return true;
}
public bool InsertIntoTable<T>(T LoginData)
where T : new()
{
conn.Insert(LoginData);
return true;
}
public bool InsertBulkIntoTable<T>(IList<T> LoginData)
where T : class //new()
{
conn.InsertAll(LoginData);
return true;
}
public List<T> SelectDataFromTable<T>()
where T : new()
{
try
{
return conn.Table<T>().ToList();
}
catch (Exception ex)
{
return null;
}
}
public List<T> SelectTableDatafromQuery<T>(string query)
where T : new()
{
return conn.Query<T>(query, new object[] { })
.ToList();
}
public bool UpdateTableData<T>(string query)
where T : new()
{
conn.Query<T>(query);
return true;
}
public void UpdateTableData<T>(IEnumerable<T> query)
where T : new()
{
conn.UpdateAll(query);
}
public void UpdateTableData<T>(T query)
where T : new()
{
conn.Update(query);
}
public bool DeleteTableData<T>(T LoginData)
{
conn.Delete(LoginData);
return true;
}
public bool DeleteTableDataFromPrimaryKey<T>(object primaryKey)
{
conn.Delete(primaryKey);
return true;
}
public bool DeleteTableDataFromQuery<T>(string query)
where T : new()
{
conn.Query<T>(query);
return true;
}
}
How should I call those method(Insert/Get/Update) from its viewmodel? Please help me,
Now for Eg: you want to insert location's Lat Long in your local database where your local model looks something like this:
public class LocationModel
{
[AutoIncrement, PrimaryKey]
public int Id { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public string Address { get; set; }
}
So first what you will do is create an instance of LocationModel something like this:
var locationModel = new LocationModel
{
Latitude = location.Latitude,
Longitude = location.Longitude
};
Then insert it something like this:
DatabaseHandler.Database.InsertIntoTable<LocationModel>(locationModel);
Also, do not forget to add the SQLiteNetExtensions in your project for Linq support.
Goodluck feel free to revert in case of queries

spring data jpa dynamic query which has IN clause

I want to create dynamic query in spring data jpa. Doing many search I can implement it, but I came across a problem when I add IN operator in where clause. I need to check id IN (longlist)
Here is my entity class
#Entity
#Table(name = "view_detail")
public class ViewDetailDom {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
#Column(name = "user_id")
private Long userId;
private String description;
Here is specification builder class and specification class
public class ViewDetailSpecificationsBuilder {
private final List<SearchCriteria> params;
public ViewDetailSpecificationsBuilder() {
params = new ArrayList<SearchCriteria>();
}
public ViewDetailSpecificationsBuilder with(String key, Operation operation, Object value) {
params.add(new SearchCriteria(key, operation, value));
return this;
}
public Specification<ViewDetailDom> build() {
if (params.size() == 0) {
return null;
}
List<Specification<ViewDetailDom>> specs = new ArrayList<Specification<ViewDetailDom>>();
for (SearchCriteria param : params) {
specs.add(new ViewDetailSpecification(param));
}
Specification<ViewDetailDom> result = specs.get(0);
for (int i = 1; i < specs.size(); i++) {
result = Specifications.where(result).and(specs.get(i));
}
return result;
}
}
public class ViewDetailSpecification implements Specification<ViewDetailDom> {
private SearchCriteria criteria = new SearchCriteria();
public ViewDetailSpecification(SearchCriteria searchCriteria) {
this.criteria.setKey(searchCriteria.getKey());
this.criteria.setOperation(searchCriteria.getOperation());
this.criteria.setValue(searchCriteria.getValue());
}
#Override
public Predicate toPredicate(Root<ViewDetailDom> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
String value = criteria.getValue().toString().replaceAll(" ", "%");
if (criteria.getOperation() != null && criteria.getOperation() != Operation.DEFAULT) {
if (criteria.getOperation() == Operation.GREATHERTHANEQUALTO) {
return builder.greaterThanOrEqualTo(root.<String>get(criteria.getKey()), value);
} else if (criteria.getOperation() == Operation.LESSTHANEQUALTO) {
return builder.lessThanOrEqualTo(root.<String>get(criteria.getKey()), value);
} else if (criteria.getOperation() == Operation.EQUAL) {
return builder.equal(root.<String>get(criteria.getKey()), value);
} else if (criteria.getOperation() == Operation.IN) {
Path<Long> view = root.<Long>get(criteria.getKey());
return view.in(criteria.getValue());
}
} else {
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(builder.lower(root.<String>get(criteria.getKey())),
"%" + value.toLowerCase() + "%");
} else {
return builder.equal(root.get(criteria.getKey()), value);
}
}
return null;
}
}
This method creates specification builder:
public ViewDetailSpecificationsBuilder createSearchSpecifications(ViewSearch view) {
ViewDetailSpecificationsBuilder builder = new ViewDetailSpecificationsBuilder();
if (StringUtils.isNotBlank(view.getName())) {
builder.with("name", Operation.DEFAULT, view.getName());
}
if (StringUtils.isNotBlank(view.getDescription())) {
builder.with("description", Operation.DEFAULT, view.getDescription());
}
return builder;
}
And finally I do this:
ViewDetailSpecificationsBuilder builder = createSearchSpecifications(view);
builder.with("userId", Operation.DEFAULT, userSessionHelper.getUserId());
builder.with("id", Operation.IN, viewids);
Specification<ViewDetailDom> spec = builder.build();
viewDetailDao.findAll(spec);
But I am getting following error:
"Unaware how to convert value [[5, 7, 8] : java.util.ArrayList] to requested type [java.lang.Long]; nested exception is java.lang.IllegalArgumentException: Unaware how to convert value [[5, 7, 8] : java.util.ArrayList] to requested type [java.lang.Long]"
I have resolved this problem in this way:
ViewDetailSpecification class:
if (criteria.getOperation() == Operation.IN) {
final List<Predicate> orPredicates = new ArrayList<Predicate>();
List<Long> viewIds = (List<Long>) criteria.getValue();
for (Long viewid : viewIds) {
orPredicates.add(builder.or(builder.equal(root.<String>get(criteria.getKey()), viewid)));
}
return builder.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
}
In kotlin I have the same error, I change the ArrayList to Array, with this code:
fun values(): Array<String> {
val elems = arrayListOf<String>()
return elems.toTypedArray()
}
Try you convert ArrayList to array, for java see: make arrayList.toArray() return more specific types

Unable to cast object of type 'System.Linq.EnumerableQuery to type 'Microsoft.Azure.Documents.Linq.IDocumentQuery

I have a class with the following Method and am using Moq as a Unit Testing Framework. How can I mock the following:
FeedOptions feedOptions = new FeedOptions
{
MaxItemCount = 1000
};
var query = await _storeAccessClient.CreateDocumentQueryAsync<CustomEntity>(_collectionLink, feedOptions)
.Where(c => c.DataType == _dataType)
.OrderBy(c => c.StartTime, sortOrder)
.AsDocumentQuery()
.ExecuteNextAsync<CustomEntity>();
List<CustomEntity> result = query.ToList<CustomEntity>();
Any Help is greatly Appreciated !!
All you have to do is create a wrapper around EnumerableQuery class which inherits from IQueryable and IDocumentQuery like this:
internal class MockEnumerableQuery : IDocumentQuery<JTokenEx>, IOrderedQueryable<JTokenEx>
{
public IQueryable<JTokenEx> List;
private readonly bool bypassExpressions;
public MockEnumerableQuery(EnumerableQuery<JTokenEx> List, bool bypassExpressions = true)
{
this.List = List;
this.bypassExpressions = bypassExpressions;
}
public IEnumerator<JTokenEx> GetEnumerator()
{
return List.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Expression Expression => List.Expression;
public Type ElementType => typeof(JTokenEx);
public IQueryProvider Provider => new MockQueryProvider(this, bypassExpressions);
public void Dispose()
{
}
public Task<FeedResponse<TResult>> ExecuteNextAsync<TResult>(CancellationToken token = new CancellationToken())
{
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
FeedResponse<JToken> feed = Activator.CreateInstance(typeof(FeedResponse<JToken>),
flags,null,new Object[] { List.Select(j => (JToken) j), 0, new NameValueCollection(), false, null}, null)
as FeedResponse<JToken>;
return Task.FromResult(feed as FeedResponse<TResult>);
}
public Task<FeedResponse<dynamic>> ExecuteNextAsync(CancellationToken token = new CancellationToken())
{
throw new NotImplementedException();
}
public bool HasMoreResults { get; }
}
class MockQueryProvider : IQueryProvider
{
private readonly MockEnumerableQuery mockQuery;
private readonly bool bypassExpressions;
public MockQueryProvider(MockEnumerableQuery mockQuery, bool byPassExpressions)
{
this.mockQuery = mockQuery;
this.bypassExpressions = byPassExpressions;
}
public IQueryable CreateQuery(Expression expression)
{
throw new NotImplementedException();
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
if (!bypassExpressions)
{
mockQuery.List = mockQuery.List.Provider.CreateQuery<TElement>(expression) as IQueryable<JTokenEx>;
}
return (IQueryable<TElement>)mockQuery;
}
public object Execute(Expression expression)
{
throw new NotImplementedException();
}
public TResult Execute<TResult>(Expression expression)
{
throw new NotImplementedException();
}
}
Now where your mock is returning EnumerableQuery, you return this MockEnumerableQuery class and you should be good.

Linq executing query generates not supported exception

I'm trying to execute a linq query in an extension method but I am getting the following exception on the ToArray() function call - it seems the query is having issues with my IList somehow, I have tried many different things and googled but fails to see the issue
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: Cannot compare elements of type 'System.Collections.Generic.IList`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'. Only primitive types, enumeration types and entity types are supported.
Code
public static IList<Shared.Poco.DimValue> ToDimValuePocoList(this IQueryable<DAL.DimValue> source)
{
IList<Shared.Poco.DimValue> values = new List<Shared.Poco.DimValue>();
foreach (DAL.DimValue dv in source.ToArray())
{
values.Add(new Shared.Poco.DimValue
{
DimensionId = dv.DimensionID,
DimValueName = dv.DimValueName,
DimValueNo = dv.DimValueNo
});
}
return values;
}
The class the calls the extension looks like this:
public class DimValue : IDimValue
{
private IDimValueRepository _repository;
private IAccessableDimensionValues _accessableDimensionValues;
private IRevision _revision;
public DimValue(IDimValueRepository reposotory, IAccessableDimensionValues accessableDimensionValues, IRevision revision)
{
_repository = reposotory;
_accessableDimensionValues = accessableDimensionValues;
_revision = revision;
}
public IList<Shared.Poco.DimValue> GetDimValueList(int budgetId, Shared.Poco.Dimension dimension, IList<string> dimensionValues, Shared.Poco.User user)
{
IList<Shared.Poco.DimValue> values = new List<Shared.Poco.DimValue>();
int budgetRevisionId = _revision.GetLatesRevision(budgetId);
IList<string> uniqueAccessableUBLValues = _accessableDimensionValues.GetUniqueAccessableDimensionValues(dimension, user.UserId, budgetRevisionId);
if (dimensionValues != null && dimensionValues.Count > 0)
{
uniqueAccessableUBLValues = dimensionValues;
}
return _repository.GetDimValueList(budgetId, dimension.ToString(), uniqueAccessableUBLValues, user).ToDimValuePocoList();
}
The implementation of the injected repository class inherits from the following base repository class
public interface IRepository<T>
{
void Insert(T entity);
void Delete(T entity);
IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
IQueryable<T> GetAll();
T GetById(int id);
}
public class Repository<T> : IRepository<T> where T : class
{
protected DbSet<T> DbSet;
public Repository(DbContext dataContext)
{
DbSet = dataContext.Set<T>();
}
#region IRepository<T> Members
public void Insert(T entity)
{
DbSet.Add(entity);
}
public void Delete(T entity)
{
DbSet.Remove(entity);
}
public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public T GetById(int id)
{
return DbSet.Find(id);
}
#endregion
}
Repository implementation
public class DimValueRepository : Repository<DimValue>, IDimValueRepository
{
public DimValueRepository(KonstruktEntities context) : base(context) { }
public IQueryable<DimValue> GetDimValueList(int budgetId, string dimensionId, IList<string> dimensionFilter, Shared.Poco.User user)
{
return this.SearchFor(dv => dv.BudgetID == budgetId && dv.DimensionID == dimensionId &&
(dimensionFilter == null || dimensionFilter.Count == 0 || dimensionFilter.Contains(dv.DimValueNo)));
}
public IQueryable<DimValue> GetDimValueList(Shared.Poco.Dimension dimension, string startsWith, Shared.Poco.User user)
{
return this.SearchFor(dv=>dv.DimensionID == dimension.ToString() &&
dv.DimValueNo.StartsWith(startsWith));
}
}
EDIT
It's failing on the following row in the ToDimValuePocoList function:
foreach (DAL.DimValue dv in source.ToArray())
Here is the row calling the extension in the DimValue class
return _repository.GetDimValueList(budgetId, dimension.ToString(), uniqueAccessableUBLValues, user).ToDimValuePocoList();
Answered by #Will in the comment above, i.e. cannot use dimensionFilter in my predicate. So I moved that logic outside of the predicate.

Do I need a Repository Class if I have a Service class and IRepository?

After reading, this question. I figured I need to look over my structure to avoid redundant code.
My current structure is Controller -> Repository -> IRepository.
The repository looks like this:
public class UserRepository : IUserRepository, IDisposable
{
private StudentSchedulingEntities _context;
public UserRepository(StudentSchedulingEntities context)
{
if (context == null)
throw new ArgumentNullException("context");
_context = context;
}
public IEnumerable<User> GetUsers()
{
return _context.Users.ToList();
}
public User GetUserByID(int id)
{
return _context.Users.Find(id);
}
public void InsertStudent(User user)
{
_context.Users.Add(user);
}
public void DeleteStudent(int userID)
{
User usr = _context.Users.Find(userID);
_context.Users.Remove(usr);
}
public void UpdateStudent(User user)
{
_context.Entry(user).State = EntityState.Modified;
}
public void Save() {
_context.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
}
}
My IRepository looks like this:
public interface IUserRepository : IDisposable
{
IEnumerable<User> GetUsers();
User GetUserByID(int userID);
void InsertStudent(User user);
void DeleteStudent(int userID);
void UpdateStudent(User user);
void Save();
}
I want to avoid doing this again in the service layer. Do I need the Repository Class or should I just implement the Service Layer in replacement of the Repository?
Your service layer won't need any repository implementations, it will simply use a repository to lookup a user, add/edit/delete a user, etc.
Now, if I can offer a bit of opinion, I'd recommend going with a generic repository. That way, if you need to make new repositories it is really simple. We use nopCommerce, and they use the following code:
public partial interface IRepository<T> where T : BaseEntity
{
T GetById(object id);
void Insert(T entity);
void Update(T entity);
void Delete(T entity);
IQueryable<T> Table { get; }
}
And since it use Entity Framework, this is the implementation:
/// <summary>
/// Entity Framework repository
/// </summary>
public partial class EfRepository<T> : IRepository<T> where T : BaseEntity
{
private readonly IDbContext _context;
private IDbSet<T> _entities;
/// <summary>
/// Ctor
/// </summary>
/// <param name="context">Object context</param>
public EfRepository(IDbContext context)
{
this._context = context;
}
public T GetById(object id)
{
return this.Entities.Find(id);
}
public void Insert(T entity)
{
try
{
if (entity == null)
throw new ArgumentNullException("entity");
this.Entities.Add(entity);
this._context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public void Update(T entity)
{
try
{
if (entity == null)
throw new ArgumentNullException("entity");
this._context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public void Delete(T entity)
{
try
{
if (entity == null)
throw new ArgumentNullException("entity");
this.Entities.Remove(entity);
this._context.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += Environment.NewLine + string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
var fail = new Exception(msg, dbEx);
//Debug.WriteLine(fail.Message, fail);
throw fail;
}
}
public virtual IQueryable<T> Table
{
get
{
return this.Entities;
}
}
private IDbSet<T> Entities
{
get
{
if (_entities == null)
_entities = _context.Set<T>();
return _entities;
}
}
//TODO implement IDisposable interface
}
Now it would be as simple as IRepository<User> or IRepository<Whatever>.
Definitely no to redundant code :-) When you say:
My current structure is Controller -> Repository ->
Is Controller inheriting from Repository? You don't want that either. The repository layer typically interfaces to storage (XML, database, file system, etc) and maps to repository friendly classes. Another layer manages the mapping of the repository layer to your native business/service classes.

Resources