I have a partial class to extend one of my LinqToSql classes. In this partial class I have the following calculated field.
public bool IsInCluster
{
get
{
return Cluster != null;
}
}
In order for a grid column databound to this field to update automatically I have implemented the following partial method.
partial void OnClusterIDChanged()
{
SendPropertyChanged("IsInCluster");
}
However when I update the Cluster property as shown in the following code the OnClusterIDChanged method does not get called:
private void ExecCreateClusterCommand()
{
var cluster = new Cluster()
{
ID = Guid.NewGuid(),
MailService = AppState.CurrentMailService
};
App.DataContext.Clusters.InsertOnSubmit(cluster);
foreach (DeliveryPoint deliveryPoint in SelectedDeliveryPoints)
{
deliveryPoint.Cluster = cluster;
}
App.DataContext.SubmitChanges();
}
I have successfully used this technique with other non navigation properties related to calculated fields. Is there a way to make this work?
In your setter for Cluster, call OnClusterIDChanged, if the state has changed.
The only solution I could find for this was to create a public method in the DeliveryPoint class enabling me to call SendPropertyChanged for the required field (navigation property):
public void CallSendPropertyChanged(string propertyName)
{
SendPropertyChanged(propertyName);
}
Related
I have the following in my project solution,am trying to maintain the Database connection of Entity framework at one place so that if I have to switch the database to a different vendor(like MYSQL to MSSQL or vice-versa) I can just change the connection name at one place and doesn't have to change at all the places...I tried the following structure but running into an error,how to fix it?
Project#1
Dashboard.EntityFramework
-->bitDbConnection.cs
using
namespace Dashboard.EntityFramework
{
public class bitDbConnection
{
BitDatabaseEntities bitDB = new BitDatabaseEntities();
}
}
Project#2
Dashboard.Repository
-->Repository.cs
using Dashboard.EntityFramework
when I try use to bitDB variable I can the below error
Error:-
The name bitDB does not exist in current context
This probably isn't what you want but to get your code to work, write it like this:
namespace Dashboard.EntityFramework
{
public class bitDbConnection
{
public BitDatabaseEntities bitDB = new BitDatabaseEntities();
}
}
using Dashboard.EntityFramework
public class Repository
{
public void DoSomething()
{
var bitDB = new bitDbConnection().bitDB;
}
}
So, first make bitDB field public, and then use it...
edit for question in comments:
public class Repository
{
private BitDatabaseEntities bitDB = new BitDatabaseEntities().bitDB;
public void DoSomething()
{
var x = bitDB.ToString();
}
}
Although I'm relatively new to AutoMapper I'm using it in a small project I'm developing. I've never had problems using it before but now I'm facing some weird behavior passing parameters to a Custom Resolver.
Here's the scenario: I get a list of messages from my repository and then map those to a frontend friendly version of it. Nothing fancy, just some normal mapping between objects. I have a field in that frontend object that tells if a certain user already voted for that message and that's what I'm using the Custom Resolver for (it's that second "ForMember"):
public List<SupportMessageUi> GetAllVisible(string userId)
{
Mapper.CreateMap<SupportMessage, SupportMessageUi>()
.ForMember(dest => dest.Votes,
opt => opt.ResolveUsing<SupportMessageVotesResolver>())
.ForMember(dest => dest.UserVoted,
opt => opt.ResolveUsing<SupportMessagesUserVotedResolver>()
.ConstructedBy(() => new SupportMessagesUserVotedResolver(userId)));
var messages = _unitOfWork.MessagesRepository.Get(m => m.Visible);
var messagesUi = Mapper.Map<List<SupportMessageUi>>(messages);
return messagesUi;
}
I'm calling this method on a web service and the problem is: the first time I call the webservice (using the webservice console) it all runs perfectly. For example, if I pass '555' as the userId I get to this method with the correct value:
And in the Custom Resolver the value was correctly passed to the constructor:
The results returned are correct. The problem comes next. The second time I call the service, passing a different argument ('666' this time) the argument that gets to the constructor of the Custom Resolver is the old one ('555'). Here's what I mean:
Right before mapping the objects we can see that the value passed to the constructor was correct ('666'):
But when it gets to the constructor of the Resolver the value is wrong, and is the old one ('555'):
All subsequent calls to the service use the original value in the Custom Resolver constructor ('555'), independently of the value I pass to the service (also happens if I make the call from another browser). If I shut down the server and relaunch it I can pass a new parameter (that will be used in all other calls until I shut it down again).
Any idea on why this is happening?
It's happening because AutoMapper.CreateMap is a static method, and only needs to be called once. With the CreateMap code in your web method, you're trying to call it every time you call that method on your web service. Since the web server process stays alive between calls (unless you restart it, like you said) then the static mappings stay in place. Hence, the necessity of calling AutoMapper.Reset, as you said in your answer.
But it's recommended that you put your mapping creation in AppStart or Global or a static constructor or whatever, so you only call it once. There are ways to call Map that allow you to pass in values, so you don't need to try to finesse things with the constructor of your ValueResolver.
Here's an example using a ValueResolver (note the change to implementing IValueResolver instead of inheriting ValueResolver<TSource, TDestination>):
[Test]
public void ValueTranslator_ExtraMapParameters()
{
const int multiplier = 2;
ValueTranslator translator = new ValueTranslator();
Mapper.AssertConfigurationIsValid();
ValueSource source = new ValueSource { Value = 4 };
ValueDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(8));
source = new ValueSource { Value = 5 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(10));
}
private class ValueTranslator
{
static ValueTranslator()
{
Mapper.CreateMap<ValueSource, ValueDest>()
.ForMember(dest => dest.Value, opt => opt.ResolveUsing<ValueResolver>().FromMember(src => src.Value));
}
public ValueDest Translate(ValueSource source, int multiplier)
{
return Mapper.Map<ValueDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class ValueResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
return source.New((int)source.Value * (int)source.Context.Options.Items["multiplier"]);
}
}
}
private class ValueSource { public int Value { get; set; } }
private class ValueDest { public int Value { get; set; } }
And here's an example using a TypeConverter:
[Test]
public void TypeTranslator_ExtraMapParameters()
{
const int multiplier = 3;
TypeTranslator translator = new TypeTranslator();
Mapper.AssertConfigurationIsValid();
TypeSource source = new TypeSource { Value = 10 };
TypeDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(30));
source = new TypeSource { Value = 15 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(45));
}
private class TypeTranslator
{
static TypeTranslator()
{
Mapper.CreateMap<TypeSource, TypeDest>()
.ConvertUsing<TypeConverter>();
}
public TypeDest Translate(TypeSource source, int multiplier)
{
return Mapper.Map<TypeDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class TypeConverter : ITypeConverter<TypeSource, TypeDest>
{
public TypeDest Convert(ResolutionContext context)
{
TypeSource source = (TypeSource)context.SourceValue;
int multiplier = (int)context.Options.Items["multiplier"];
return new TypeDest { Value = source.Value * multiplier };
}
}
}
private class TypeSource { public int Value { get; set; } }
private class TypeDest { public int Value { get; set; } }
Answering myself: I was not using AutoMapper.Reset(). Once I did that everything started working properly.
Helpful reading: http://www.markhneedham.com/blog/2010/01/27/automapper-dont-forget-mapper-reset-at-the-start/
I've inherited a system that uses the Castle Windsor IRepository pattern to abstract away from the DAL which is LinqToSQL.
The main problem that I can see, is that IRepository only implements IEnumerable. So even the simplest of queries have to load ALL the data from the datatable, to return a single object.
Current usage is as follows
using (IUnitOfWork context2 = IocServiceFactory.Resolve<IUnitOfWork>())
{
KpiFormDocumentEntry entry = context2.GetRepository<KpiFormDocumentEntry>().FindById(id, KpiFormDocumentEntry.LoadOptions.FormItem);
And this uses lambda to filter, like so
public static KpiFormDocumentEntry FindById(this IRepository<KpiFormDocumentEntry> source, int id, KpiFormDocumentEntry.LoadOptions loadOptions)
{
return source.Where( qi => qi.Id == id ).LoadWith( loadOptions ).FirstOrDefault();
}
So it becomes a nice extension method.
My Question is, how can I use this same Interface/pattern etc. but also implement IQueryable to properly support LinqToSQL and get some serious performance improvements?
The current implementation/Interfaces for IRepository are as follows
public interface IRepository<T> : IEnumerable<T> where T : class
{
void Add(T entity);
void AddMany(IEnumerable<T> entities);
void Delete(T entity);
void DeleteMany(IEnumerable<T> entities);
IEnumerable<T> All();
IEnumerable<T> Find(Func<T, bool> predicate);
T FindFirst(Func<T, bool> predicate);
}
and then this is implemented by an SqlClientRepository like so
public sealed class SqlClientRepository<T> : IRepository<T> where T : class
{
private readonly Table<T> _source;
internal SqlClientRepository(Table<T> source)
{
if( source == null ) throw new ArgumentNullException( "source", Gratte.Aurora.SHlib.labelText("All_TableIsNull",1) );
_source = source;
}
//removed add delete etc
public IEnumerable<T> All()
{
return _source;
}
public IEnumerator<T> GetEnumerator()
{
return _source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
The problem at the moment is, in our example above, the .Where is calling 'GetEnumerator', which then loads all rows into memory, and then looks for the one we need.
If I change IRepository to implement IQueryable, I can't implement the three methods needed, as these are not public in the Table class.
I think I should change the SQLClientRepository to be defined like so
public sealed class SqlClientRepository<T> : IQueryable<T>, IRepository<T> where T : class
And then implement the necessary methods, but I can't figure out how to pass the expressions around etc. as they are private members of the Table class, like so
public override Type ElementType
{
get { return _source.ElementType; } //Won't work as ElementType is private
}
public override Expression Expression
{
get { return _source.Expression; } //Won't work as Expression is private
}
public override IQueryProvider Provider
{
get { return _source.Provider; } //Won't work as Provider is private
}
Any help really appreciated to move this from 'iterate through every row in the database after loading it' to 'select x where id=1'!
If you want to expose linq you can stop using the repository pattern and use Linq2Sql directly. The reason to this is that every Linq To Sql provider has it's own custom solutions. So if you expose LINQ you get a leaky abstraction. There is no point in using an abstraction layer then.
Instead of exposing LINQ you got two options:
Implement the specification pattern
Use the repository pattern as I describe here: http://blog.gauffin.org/2013/01/repository-pattern-done-right/
So, while it may not be a true abstraction any longer, the main point was to get the benefit of linq to sql without updating all the queries already written.
so, I made the IRepository implement IQueryable instead of IEnumerable.
then in the SqlClientRepository implementation, I can call AsQueryable() to cast the Table to IQueryable, and then all is good, like so.
Now everywhere somebody has written IRepository().Where(qi => qi.id = id) or similar, it actually passes the ID to sql server and only pulls back one record, instead of all of them, and loops through looking for the correct one.
/// <summary>Provides the ability to query and access entities within a SQL Server data store.</summary>
/// <typeparam name="T">The type of entity in the repository.</typeparam>
public sealed class SqlClientRepository<T> : IRepository<T> where T : class
{
private readonly Table<T> _source;
private readonly IQueryable<T> _sourceQuery;
IQueryable<T> Query()
{
return (IQueryable<T>)_source;
}
public Type ElementType
{
get { return _sourceQuery.GetType(); }
}
public Expression Expression
{
get { return _sourceQuery.Expression; }
}
public IQueryProvider Provider
{
get { return _sourceQuery.Provider; }
}
/// <summary>Initializes a new instance of the <see cref="SqlClientRepository{T}"/> class.</summary>
/// <param name="source">A <see cref="Table{T}"/> to a collection representing the entities from a SQL Server data store.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is a <c>null</c> reference (<c>Nothing</c> in Visual Basic).</exception>
internal SqlClientRepository(Table<T> source)
{
if( source == null ) throw new ArgumentNullException( "source", "All_TableIsNull" ) );
_source = source;
_sourceQuery = _source.AsQueryable();
}
I have a group of classes that implement an interface for my application start-up activities. Here is the registration code:
private static void ConfigureContainer()
{
var container = new WindsorContainer();
container.Register(AllTypes.Of<IStartupTask>()
.FromAssembly(Assembly.GetExecutingAssembly()))
...
var serviceLocator = container.Resolve<IServiceLocator>();
ServiceLocator.SetLocatorProvider(() => serviceLocator);
}
In order to get the tasks, I use this and it works as expected:
public static void Run()
{
var tasks = ServiceLocator.Current.GetAllInstances<IStartupTask>();
foreach (var task in tasks)
{
task.Execute();
}
}
Here is my problem: I have one task that depends on another being run first. There is an InitializeDatabase task that needs to run before the PopulateDatabse task. There are also a bunch of other tasks that are run and I would rather not split the InitializeDatabase task out, if there is some Castle config that will allow me to order the resolution of the types. I don't want to specify the complete order of the types being resolved since that defeats the purpose of the automatic registration, just that InitializeDatabase is the first or PopulateDatabase is last.
Is there a way to register which types should be resolved first without specifying the order of all the types?
Here's one way to do it, it might not be very pretty but it works:
[AttributeUsage(AttributeTargets.Class)]
public class FirstAttribute: Attribute {}
public interface IService {}
public class ThirdService : IService { }
[First]
public class FirstService : IService { }
public class SecondService: IService {}
[Test]
public void WindsorOrder() {
var container = new WindsorContainer();
container.Register(AllTypes.Of<IService>()
.FromAssembly(Assembly.GetExecutingAssembly()));
var intf = container.ResolveAll<IService>()
.OrderByDescending(i => i.GetType().GetCustomAttributes(typeof(FirstAttribute), true).Length)
.ToArray();
Assert.IsInstanceOfType(typeof(FirstService), intf[0]);
}
If you remove [First] from FirstService, the first will be ThirdService and the test will fail.
Use HandlerSelector for that
How come the "Table" classes Generated in the Dbml do not contain useful events like
OnBeforeInsert
OnBeforeUpdate
OnAfterInsert
etc.
Am I missing something?
This question is related to frustration trying to set timestamp columns.
UPDATE
I created the following method of doing this neatly what does everyone think?
public class Model
{
internal virtual void OnBeforeInsert()
{
}
internal virtual void OnBeforeUpdate()
{
}
}
public partial class DbDataContext
{
public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
{
foreach (var insert in this.GetChangeSet().Inserts)
{
if (insert is Model)
{
((Model)insert).OnBeforeInsert();
}
}
foreach (var update in this.GetChangeSet().Updates)
{
if (update is Model)
{
((Model)update).OnBeforeUpdate();
}
}
base.SubmitChanges(failureMode);
}
}
public partial class Address : Model
{
internal override void OnBeforeInsert()
{
var created = DateTime.Now;
this._Modified = created;
this._Created = created;
}
}
I had a similar issue like this recently.
There is a partial method in the generated class for "OnValidate". Simply declaring the method in your partial will force it to be called (vb.net does not support partial methods like c#) or in c# simply declare a partial method.
The method is passed a System.Data.Linq.ChangeAction enum that is either: Delete, Insert, Update, or None.
Below is a sample of what you did using the built in partial method.
public partial class Address
{
private partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if (action == System.Data.Linq.ChangeAction.Insert)
{
var created = DateTime.Now;
this._Modified = created;
this._Created = created;
} else if (action == System.Data.Linq.ChangeAction.Update) {
this._Modified = DateTime.Now;
}
}
}