Telerik Scheduler "UniqueId property" - how to access it - telerik-scheduler

i use Telerik Demo Sheduler as my base. I have modified data loading like this:
public class SessionAppointmentCollection : ObservableCollection<SessionAppointment>, IAppointmentFactory
{
/// <summary>
/// Gets sample appointments.
/// </summary>
/// <value>The appointments.</value>
public SessionAppointmentCollection(RadScheduler scheduler)
{
// int month = DateTime.Now.Month;
// DateTime mondayDate = CalendarHelper.GetFirstDayOfWeek(DateTime.Today, DayOfWeek.Monday);
// DateTime satDate = CalendarHelper.GetFirstDayOfWeek(DateTime.Today, DayOfWeek.Saturday);
// DateTime lastsundayDate = CalendarHelper.GetEndOfMonth(DateTime.Today);
DataTable dtActions = SqlHelper.GetTable("base_Action_Search");//, new string[] { "#CompanyName", client, "#TaskTypeID", db_TaskTypeID.SelectedValue.ToString() });//, "#Users", Users });
foreach (DataRow dr in dtActions.Rows)
{
SessionAppointment appointmentas = new SessionAppointment();
appointmentas.UniqueId = dr["ActionID"].ToString();
appointmentas.Subject = dr["ActionName"].ToString();
appointmentas.Body = dr["Comments"].ToString();
DateTime start = Convert.ToDateTime(dr["StartDate"].ToString());
appointmentas.Start = start;
appointmentas.End = start.AddMinutes(Convert.ToInt32(dr["Duration"].ToString()));
appointmentas.SessionRoom = "01";
appointmentas.Speaker = "Testinis vartotojas";
appointmentas.Level = 300;
appointmentas.Category = dr["Priority"].ToString().Equals("-1") ? scheduler.Categories.GetCategoryByName("WebDevelopement") : scheduler.Categories.GetCategoryByName("WindowsAndFrameworks"); ;
Add(appointmentas);
}
Now i want to implement deleting. But i cant access UniqueID property? How I can do that..?

The post below sheds some light on that:
http://www.telerik.com/community/forums/wpf/scheduler/uniqueid-property-how-to-access-it.aspx
Basically, you will have to cast the e.Appointment argument (because it is of type IAppointment) of the AppointmentDeletedEventArgs to RadScheduler's Appointment object in order to have access to UniqueId.

This article gives the following answer, which should work for you:
Appointment appointment = appointmentElement.Appointment as Appointment;
Guid appId = appointment.UniqueId;

Related

Calling 'Read' when the data reader is closed is not a valid operation error using Entity Framework database first approach

I am creating a Web API that will fetch information from a table using Entity Framework database-first approach using stored procedures. ListAllTeams_Result is the complex type object created in Entity Framework. I am looping through the import function GetAllTeams() and populating the complex type. I am getting an error in my business layer when trying to access the data access layer
The error that I am getting is the following code
var team = _teamRepository.GetAllTeams();
The result of the query cannot be enumerated more than once.
Note: this error is in the inner stack and doesn't stop the application from executing
foreach (var t in team)
Calling 'Read' when the data reader is closed is not a valid operation.
Note : This stops execution
Business Layer
public IEnumerable<TeamDto> GetTeam()
{
var team = _teamRepository.GetAllTeams();
if (team != null)
{
foreach (var t in team.ToList())
{
yield return Mapper.Map<TeamDto>(t);
}
}
yield break;
}
DataAccess layer:
public IEnumerable<ListAllTeams_Result> GetAllTeams()
{
using (var mcrContext = new MCREntities())
{
return (from team in mcrContext.ListAllTeams("")
select new ListAllTeams_Result
{
TeamID = team.TeamID,
TeamDescription = team.TeamDescription,
CountryCode = team.CountryCode,
CreatedBy = team.CreatedBy,
CreatedDate = team.CreatedDate,
ModifiedBy = team.ModifiedBy,
ModifiedDate = team.ModifiedDate
});
}
}
I have found what the problem is. I had to add ToList in the return
using (var mcrContext = new MCREntities())
{
return (from team in mcrContext.ListAllTeams("")
select new ListAllTeams_Result
{
TeamID = team.TeamID,
TeamName = team.TeamName,
TeamDescription = team.TeamDescription,
CountryCode = team.CountryCode,
CreatedBy = team.CreatedBy,
CreatedDate = team.CreatedDate,
ModifiedBy = team.ModifiedBy,
ModifiedDate = team.ModifiedDate
}).ToList();
}

Entity Framework cycle of data

I have an Account object, which has many Transactions related to it.
In one method, I get all transactions for a particular account.
var transactionlines = (from p in Context.account_transaction
.Include("account_transaction_line")
// .Include("Account")
.Include("account.z_account_type")
.Include("account.institution")
.Include("third_party")
.Include("third_party.z_third_party_type")
.Include("z_account_transaction_type")
.Include("account_transaction_line.transaction_sub_category")
.Include("account_transaction_line.transaction_sub_category.transaction_category")
.Include("z_account_transaction_entry_type")
.Include("account_transaction_line.cost_centre")
where p.account_id == accountId
&& p.deleted == null
select p).ToList();
This is meant to return me a list of transactions, with their related objects. I then pass each object to a Translator, which translates them into data transfer objects, which are then passed back to my main application.
public TransactionDto TranslateTransaction(account_transaction source)
{
LogUserActivity("in TranslateTransaction");
var result = new TransactionDto
{
Id = source.id,
Version = source.version,
AccountId = source.account_id,
// Account = TranslateAccount(source.account, false),
ThirdPartyId = source.third_party_id,
ThirdParty = TranslateThirdParty(source.third_party),
Amount = source.transaction_amount,
EntryTypeId = source.account_transaction_entry_type_id,
EntryType = new ReferenceItemDto
{
Id = source.account_transaction_entry_type_id,
Description = source.z_account_transaction_entry_type.description,
Deleted = source.z_account_transaction_entry_type.deleted != null
},
Notes = source.notes,
TransactionDate = source.transaction_date,
TransactionTypeId = source.account_transaction_type_id,
TransactionType = new ReferenceItemDto
{
Id = source.z_account_transaction_type.id,
Description = source.z_account_transaction_type.description,
Deleted = source.z_account_transaction_type.deleted != null
}
};
... return my object
}
The problem is:
An account has Transactions, and a Transaction therefore belongs to an Account. It seems my translators are being called way too much, and reloading a lot of data because of this.
When I load my transaction object, it's 'account' property has a'transactions' propery, which has a list of all the transactions associated to that account. Each transaction then has an account property... and those account peroprties again, have a list of all the transactions... and on and on it goes.
Is there a way I can limit the loading to one level or something?
I have this set:
Context.Configuration.LazyLoadingEnabled = false;
I was hoping my 'Includes' would be all that is loaded... Don't load 'un-included' related data?
As requested, here is my TranslateAccount method:
public AccountDto TranslateAccount(account p, bool includeCardsInterestRateDataAndBalance)
{
LogUserActivity("in TranslateAccount");
if (p == null)
return null;
var result =
new AccountDto
{
Id = p.id,
Description = p.description,
PortfolioId = p.institution.account_portfolio_id,
AccountNumber = p.account_number,
Institution = TranslateInstitution(p.institution),
AccountType = new ReferenceItemDto
{
Id = p.account_type_id,
Description = p.z_account_type.description
},
AccountTypeId = p.account_type_id,
InstitutionId = p.institution_id,
MinimumBalance = p.min_balance,
OpeningBalance = p.opening_balance,
OpeningDate = p.opening_date
};
if (includeCardsInterestRateDataAndBalance)
{
// Add the assigned cards collection
foreach (var card in p.account_card)
{
result.Cards.Add(new AccountCardDto
{
Id = card.id,
AccountId = card.account_id,
Active = card.active,
CardHolderName = card.card_holder_name,
CardNumber = card.card_number,
ExpiryDate = card.expiry
});
}
// Populate the current interest rate
result.CurrentRate = GetCurrentInterestRate(result.Id);
// Add all rates to the account
foreach (var rate in p.account_rate)
{
result.Rates.Add(
new AccountRateDto
{
Id = rate.id,
Description = rate.description,
Deleted = rate.deleted != null,
AccountId = rate.account_id,
EndDate = rate.end_date,
Rate = rate.rate,
StartDate = rate.start_date
});
}
result.CurrentBalance = CurrentBalance(result.Id);
}
LogUserActivity("out TranslateAccount");
return result;
}
The entity framework context maintains a cache of data that has been pulled out of the database. Regardless of lazy loading being enabled/disabled, you can call Transaction.Account.Transactions[0].Account.Transactions[0]... as much as you want without loading anything else from the database.
The problem is not in the cyclical nature of entity framework objects - it is somewhere in the logic of your translation objects.

How can I post a list then access it in my controller?

I created a list property in my model like so
public virtual List<String> listOfDays { get; set; }
then I converted and stored it in the list like this:
for (int i = 0; i < 30 i++)
{
var enrollment = new Enrollment();
enrollment.StudentID = id;
enrollment.listOfDays = searchString.ToList();
db.Enrollments.Add(enrollment);
db.SaveChanges();
}
I put a breakpoint here... enrollment.listOfDays = searchString.ToList(); ... and all is well. I see that the conversion was performed and I can see the values in listOfDays.
So I thought I would find a column in my database called listOfDays since I'm doing code first but the property is not there.
Then I thought I'd try accessing it anyway like this...
var classdays = from e in db.Enrollments where e.StudentID == id select e.listOfDays;
var days = classdays.ToList();
//here I get an error message about this not being supported in Linq.
Questions:
Why do you think the property was not in the database?
How can I post this array to my model then access it in a controller?
Thanks for any help.
Thanks to Decker: http://forums.asp.net/members/Decker%20Dong%20-%20MSFT.aspx
Here’s how it works:
Using form collection here…
In [HttpPost]…
private void Update (FormCollection formCollection, int id)
for (int sc = 0; sc < theSelectedCourses.Count(); sc++)
{
var enrollment = new Enrollment();
enrollment.CourseID = Convert.ToInt32(theSelectedCourses[sc]);
enrollment.StudentID = id;
enrollment.listOfDays = formCollection["searchString"] ;//bind this as a string instead of a list or array.
Then in [HttpGet]…
private void PopulateAssignedenrolledData(Student student, int id)
{
var dayList = from e in db.Enrollments where e.StudentID == id select e;
var days = dayList.ToList();
if (days.Count > 0)
{
string dl = days.FirstOrDefault().listOfDays;
string[] listofdays = dl.Split(',');
ViewBag.classDay = listofdays.ToList();
}
Thanks to Decker: http://forums.asp.net/members/Decker%20Dong%20-%20MSFT.aspx
Here’s how it works:
Using form collection here…
In [HttpPost]…
private void Update (FormCollection formCollection, int id)
for (int sc = 0; sc < theSelectedCourses.Count(); sc++)
{
var enrollment = new Enrollment();
enrollment.CourseID = Convert.ToInt32(theSelectedCourses[sc]);
enrollment.StudentID = id;
enrollment.listOfDays = formCollection["searchString"] ;//bind this as a string instead of a list or array.
Then in [HttpGet]…
private void PopulateAssignedenrolledData(Student student, int id)
{
var dayList = from e in db.Enrollments where e.StudentID == id select e;
var days = dayList.ToList();
if (days.Count > 0)
{
string dl = days.FirstOrDefault().listOfDays;
string[] listofdays = dl.Split(',');
ViewBag.classDay = listofdays.ToList();
}

Filtering Telerik MVC Grid on Date only (neglect time values)

I have a column in Telerik MVC Grid which is of type DateTime. I want to only use the Date part of it for display and filtering. As a result, I used the following code
#(Html.Telerik().Grid<State>()
.Name("tlkStateGrid")
.Columns(col => {
col.Bound(m => m.CreatedOn).Title("Created On").Format("{0:dd/MM/yyyy}");
The Grid does display the Date (CreatedOn) in the format specified. However, the filtering doesn't work as expected. I think that while filtering, the time values are considered too by the Grid. So if two dates are same but having different time values, they are not considered 'equal'.
How do I configure grid to neglect the time values and compare only dates, when filtering.
Note: I have posted similar question in Telerik MVC forums but no answer as yet.
You could modify lambda expression to explicitly modify the CreatedOn property to be just a date. You'll get just the date component of the datetime object.
col.Bound(m => m.CreatedOn.Date)
You new code will now be as below.
#(Html.Telerik().Grid<State>()
.Name("tlkStateGrid")
.Columns(col => {
col.Bound(m => m.CreatedOn.Date).Title("Created On").Format({0:dd/MM/yyyy}");
if CreatedOn is a nullable datetime you'll need to access its Value property before getting the Date component. See below.
col.Bound(m => m.CreatedOn.HasValue? m.CreatedOn.Value.Date : m.CreatedOn)
I've created the following code which changes the way a date-filter is defined:
/// <summary>
/// Maps DateTime related filters.
/// * IsEqualTo filter is converted to ('x-date' is GreaterThanOrEqualTo 'SearchDate') AND ('x-date' is LessThan 'SearchDate' + 1 Day)
/// * IsNotEqualTo filter is converted to ('x-date' LessThan 'SearchDate') OR ('x-date' is GreaterThan 'SearchDate' + 1 Day) OR ('x-date' is NULL)
/// * IsLessThanOrEqualTo filter is converted to ('x-date' is LessThan 'SearchDate' + 1 Day)
/// </summary>
/// <param name="copyOfOriginalFilters">A copy from the filters.</param>
/// <param name="newFilters">The new filters</param>
protected void MapDateFilter(ReadOnlyCollection<IFilterDescriptor> copyOfOriginalFilters, IList<IFilterDescriptor> newFilters)
{
newFilters.Clear();
foreach (var currentFilter in copyOfOriginalFilters)
{
Type t = currentFilter.GetType();
if (t == typeof(FilterDescriptor))
{
var filter = currentFilter as FilterDescriptor;
if (filter.ConvertedValue.GetType() == typeof(DateTime))
{
DateTime datePart = ((DateTime)filter.ConvertedValue).Date;
if (filter.Operator == FilterOperator.IsEqualTo)
{
var compositeFilter = new CompositeFilterDescriptor();
compositeFilter.FilterDescriptors.Add(new FilterDescriptor(filter.Member, FilterOperator.IsGreaterThanOrEqualTo, datePart));
compositeFilter.FilterDescriptors.Add(new FilterDescriptor(filter.Member, FilterOperator.IsLessThan, datePart.AddDays(1)));
compositeFilter.LogicalOperator = FilterCompositionLogicalOperator.And;
newFilters.Add(compositeFilter);
}
else if (filter.Operator == FilterOperator.IsNotEqualTo)
{
var compositeFilter = new CompositeFilterDescriptor();
compositeFilter.FilterDescriptors.Add(new FilterDescriptor(filter.Member, FilterOperator.IsLessThan, datePart));
compositeFilter.FilterDescriptors.Add(new FilterDescriptor(filter.Member, FilterOperator.IsGreaterThan, datePart.AddDays(1)));
compositeFilter.FilterDescriptors.Add(new FilterDescriptor(filter.Member, FilterOperator.IsEqualTo, null));
compositeFilter.LogicalOperator = FilterCompositionLogicalOperator.Or;
newFilters.Add(compositeFilter);
}
else if (filter.Operator == FilterOperator.IsLessThanOrEqualTo)
{
newFilters.Add(new FilterDescriptor(filter.Member, FilterOperator.IsLessThan, datePart.AddDays(1)));
}
else
{
newFilters.Add(filter);
}
}
else
{
newFilters.Add(filter);
}
}
else if (t == typeof(CompositeFilterDescriptor))
{
var filter = currentFilter as CompositeFilterDescriptor;
int numberOfDateFilters = filter.FilterDescriptors.Where(fd =>
fd is FilterDescriptor &&
(fd as FilterDescriptor).ConvertedValue != null &&
(fd as FilterDescriptor).ConvertedValue.GetType() == typeof(DateTime))
.Count();
if (numberOfDateFilters == 2)
{
var firstFilter = filter.FilterDescriptors[0] as FilterDescriptor;
firstFilter.Value = ((DateTime)firstFilter.ConvertedValue).Date;
var secondFilter = filter.FilterDescriptors[1] as FilterDescriptor;
secondFilter.Value = ((DateTime)secondFilter.ConvertedValue).Date;
}
else
{
MapDateFilter(new List<IFilterDescriptor>(filter.FilterDescriptors).AsReadOnly(), filter.FilterDescriptors);
}
newFilters.Add(filter);
}
}
}
This can be used like:
protected void MapGridCommand(GridCommand command)
{
this.MapDateFilter(new List<IFilterDescriptor>(command.FilterDescriptors).AsReadOnly(), command.FilterDescriptors);
}

How can I do an OrderBy with a dynamic string parameter?

I want to do this:
var orderBy = "Nome, Cognome desc";
var timb = time.Timbratures.Include("Anagrafica_Dipendente")
.Where(p => p.CodDipendente == 1);
if(orderBy != "")
timb = timb.OrderBy(orderBy);
Is there an OrderBy overload available that accepts a string parameter?
If you are using plain LINQ-to-objects and don't want to take a dependency on an external library it is not hard to achieve what you want.
The OrderBy() clause accepts a Func<TSource, TKey> that gets a sort key from a source element. You can define the function outside the OrderBy() clause:
Func<Item, Object> orderByFunc = null;
You can then assign it to different values depending on the sort criteria:
if (sortOrder == SortOrder.SortByName)
orderByFunc = item => item.Name;
else if (sortOrder == SortOrder.SortByRank)
orderByFunc = item => item.Rank;
Then you can sort:
var sortedItems = items.OrderBy(orderByFunc);
This example assumes that the source type is Item that have properties Name and Rank.
Note that in this example TKey is Object to not constrain the property types that can be sorted on. If the func returns a value type (like Int32) it will get boxed when sorting and that is somewhat inefficient. If you can constrain TKey to a specific value type you can work around this problem.
Absolutely. You can use the LINQ Dynamic Query Library, found on Scott Guthrie's blog. There's also an updated version available on CodePlex.
It lets you create OrderBy clauses, Where clauses, and just about everything else by passing in string parameters. It works great for creating generic code for sorting/filtering grids, etc.
var result = data
.Where(/* ... */)
.Select(/* ... */)
.OrderBy("Foo asc");
var query = DbContext.Data
.Where(/* ... */)
.Select(/* ... */)
.OrderBy("Foo ascending");
Another solution from codeConcussion (https://stackoverflow.com/a/7265394/2793768)
var param = "Address";
var pi = typeof(Student).GetProperty(param);
var orderByAddress = items.OrderBy(x => pi.GetValue(x, null));
The simplest & the best solution:
mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s));
You don't need an external library for this. The below code works for LINQ to SQL/entities.
/// <summary>
/// Sorts the elements of a sequence according to a key and the sort order.
/// </summary>
/// <typeparam name="TSource">The type of the elements of <paramref name="query" />.</typeparam>
/// <param name="query">A sequence of values to order.</param>
/// <param name="key">Name of the property of <see cref="TSource"/> by which to sort the elements.</param>
/// <param name="ascending">True for ascending order, false for descending order.</param>
/// <returns>An <see cref="T:System.Linq.IOrderedQueryable`1" /> whose elements are sorted according to a key and sort order.</returns>
public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> query, string key, bool ascending = true)
{
if (string.IsNullOrWhiteSpace(key))
{
return query;
}
var lambda = (dynamic)CreateExpression(typeof(TSource), key);
return ascending
? Queryable.OrderBy(query, lambda)
: Queryable.OrderByDescending(query, lambda);
}
private static LambdaExpression CreateExpression(Type type, string propertyName)
{
var param = Expression.Parameter(type, "x");
Expression body = param;
foreach (var member in propertyName.Split('.'))
{
body = Expression.PropertyOrField(body, member);
}
return Expression.Lambda(body, param);
}
(CreateExpression copied from https://stackoverflow.com/a/16208620/111438)
I did so:
using System.Linq.Expressions;
namespace System.Linq
{
public static class LinqExtensions
{
public static IOrderedQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string field, string dir = "asc")
{
// parametro => expressão
var parametro = Expression.Parameter(typeof(TSource), "r");
var expressao = Expression.Property(parametro, field);
var lambda = Expression.Lambda(expressao, parametro); // r => r.AlgumaCoisa
var tipo = typeof(TSource).GetProperty(field).PropertyType;
var nome = "OrderBy";
if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
{
nome = "OrderByDescending";
}
var metodo = typeof(Queryable).GetMethods().First(m => m.Name == nome && m.GetParameters().Length == 2);
var metodoGenerico = metodo.MakeGenericMethod(new[] { typeof(TSource), tipo });
return metodoGenerico.Invoke(source, new object[] { source, lambda }) as IOrderedQueryable<TSource>;
}
public static IOrderedQueryable<TSource> ThenBy<TSource>(this IOrderedQueryable<TSource> source, string field, string dir = "asc")
{
var parametro = Expression.Parameter(typeof(TSource), "r");
var expressao = Expression.Property(parametro, field);
var lambda = Expression.Lambda<Func<TSource, string>>(expressao, parametro); // r => r.AlgumaCoisa
var tipo = typeof(TSource).GetProperty(field).PropertyType;
var nome = "ThenBy";
if (string.Equals(dir, "desc", StringComparison.InvariantCultureIgnoreCase))
{
nome = "ThenByDescending";
}
var metodo = typeof(Queryable).GetMethods().First(m => m.Name == nome && m.GetParameters().Length == 2);
var metodoGenerico = metodo.MakeGenericMethod(new[] { typeof(TSource), tipo });
return metodoGenerico.Invoke(source, new object[] { source, lambda }) as IOrderedQueryable<TSource>;
}
}
}
Use :
example.OrderBy("Nome", "desc").ThenBy("other")
Work like:
example.OrderByDescending(r => r.Nome).ThenBy(r => r.other)
Look at this blog here. It describes a way to do this, by defining an EntitySorter<T>.
It allows you to pass in an IEntitySorter<T> into your service methods and use it like this:
public static Person[] GetAllPersons(IEntitySorter<Person> sorter)
{
using (var db = ContextFactory.CreateContext())
{
IOrderedQueryable<Person> sortedList = sorter.Sort(db.Persons);
return sortedList.ToArray();
}
}
And you can create an EntitiySorter like this:
IEntitySorter<Person> sorter = EntitySorter<Person>
.OrderBy(p => p.Name)
.ThenByDescending(p => p.Id);
Or like this:
var sorter = EntitySorter<Person>
.OrderByDescending("Address.City")
.ThenBy("Id");
You need to use the LINQ Dynamic Query Library in order to pass parameters at runtime,
This will allow linq statements like
string orderedBy = "Description";
var query = (from p in products
orderby(orderedBy)
select p);
If your columnName is in a variable col, then
string col="name";
list.OrderBy(x=>x[col])
As what Martin Liversage said, you can define a Func<>before you pass it to OrderBy method, but I found an interesting way to do that.
You can define a dictionary from string to Func<> like this :
Dictionary<string, Func<Item, object>> SortParameters = new Dictionary<string, Func<Item, object>>()
{
{"Rank", x => x.Rank}
};
And use it like this :
yourList.OrderBy(SortParameters["Rank"]);
In this case you can dynamically sort by string.
In one answer above:
The simplest & the best solution:
mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s));
There is an syntax error, ,null must be added:
mylist.OrderBy(s => s.GetType().GetProperty("PropertyName").GetValue(s,null));

Resources