Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4565426
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T18:38:30+00:00 2026-05-21T18:38:30+00:00

I am currently working on an application that has all its entities coming from

  • 0

I am currently working on an application that has all its entities coming from straight from Linq2SQL. Trying to find a way to keep everything cleanly separated, I added a domain model for the type that came from Linq2SQL and wrapped that with a ViewModel.

This added a little bit of complexity to my code, as I have a service layer and in it when initializing I got the entity from L2S, newed my domain class, and filled it with whatever data was in the entity.

When I wanted to insert the item back into the database in L2S, I ran into a problem which made me do the reverse: fill an entity with the data from the domain class. At this point I started to doubt if I was on the right path, so I started to think about what I have done wrong, or just possibly thought was the right way but ultimately wasn’t.

I ended up thinking that wrapping the entity instead of filling a domain model and wrapping that, was maybe the right way to go in this situation. If I wouldn’t do something like this, I would need to have a using statement in the ViewModel of my View pointing to the DAL. Maybe I’m mistaken, but as far as I read (in books, internet articles), that is not a clean separation of concerns.

So, hence my question:

When there are no domain models, is the ViewModel for the Model used to keep the DAL out of the ViewModel of the View?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T18:38:30+00:00Added an answer on May 21, 2026 at 6:38 pm

    Your question is a bit vague. However I see a lot of confusion in the comunity about the MVVM pattern. A lot of people “Wrap” the model in the ViewModel, like what you’re doing, and this is wrong.

    The Model is basically your L2S Objects.

    The ViewModel, exposes the L2S objects directly, and handles interaction logic, i.e. handle commands, object updates, etc. (doesn’t wrap anything, just as a link to them).

    Wraping is wrong, let’s say for example that you want something that is too complex for a converter, yet you need to have it on your Entity (BusinessObject or whatever comes out of L2S – Your ORM framework), you should extend your Entity to support this.

    I’ll give you some examples, however these are from a slightly different architecture:

    • Entity Framework 4.1
    • Prism, MVVM implementation
    • MEF Dependency Injection Container

    This is a list of Tasks in this application, the final result is a view like project with a gantt chart.

    The ViewModel looks like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.Composition;
    using Sigep.Common.Interfaces;
    using Microsoft.Practices.Prism.Regions;
    using Microsoft.Practices.Prism.ViewModel;
    using System.Windows.Input;
    using System.Diagnostics;
    using Sigep.Common.DataSelfTracking;
    using System.Windows.Data;
    using System.Globalization;
    using System.Windows;
    using System.Collections.ObjectModel;
    using System.Windows.Media;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Sigep.WPF.Controls.Cronograma
    {
        [Export(typeof(TarefasListViewModel))]
        [PartCreationPolicy(CreationPolicy.NonShared)]
        public class TarefasListViewModel : NotificationObject
        {
            private IDataManager _data;
            private IRegionManager _regionManager;
    
            private static ObservableCollection<Tarefa> _tarefas;
            private static List<Sigep.Common.DataSelfTracking.Tarefa> _tarefasList;
    
            [ImportingConstructor]
            public TarefasListViewModel(IRegionManager regionManager, IDataManager data)
            {
                _data = data;
                _regionManager = regionManager;
    
                _tarefas = new ObservableCollection<Tarefa>(_data.TarefaList.OrderBy(T => T.Codigo));
                _tarefasList = _data.TarefaList;
    
                _data.Loaded += new EventHandler<DataManagerEventArgs>(Data_Loaded);
    
                _NovaTarefa_Command = new DelegateCommand(this.NovaTarefa);
            }
    
            void Data_Loaded(object sender, DataManagerEventArgs e)
            {
                Task.Factory.StartNew(() =>
                {
                    _tarefas.Clear();
                    foreach (var tarefa in _data.TarefaList.OrderBy(T => T.Codigo)) _tarefas.Add(tarefa);
                    RaisePropertyChanged(() => this.Promotores);
                }
                , CancellationToken.None
                , TaskCreationOptions.None
                , Indra.Injection.ServiceLocator.MefContainer.GetExportedValue<TaskScheduler>());
            }
    
            public ObservableCollection<Tarefa> Tarefas
            {
                get
                {
                    return _tarefas;
                }
            }
    
            public static void refreshTarefas()
            {
                _tarefas.Clear();
                foreach (var tarefa in _tarefasList.OrderBy(T => T.Codigo)) _tarefas.Add(tarefa);
            }
    
    
            public IEnumerable<PromotorIndex> Promotores
            {
                get
                {
                    int index = 0;
                    foreach (var promotor in _data.Candidatura.Promotores.OrderBy(p => p.Nome))
                    {
                        yield return new PromotorIndex()
                        {
                            Nome = promotor.Nome,
                            Index = index++
                        };
                    }
                }
            }
            private ICommand _NovaTarefa_Command;
            public ICommand NovaTarefa_Command { get { return this._NovaTarefa_Command; } }
            private void NovaTarefa()
            {
                Tarefa tarefa = new Tarefa { Inicio = DateTime.Now, Fim = DateTime.Now, Nome = "",Actividade = _data.ActividadeList.FirstOrDefault() };
    
                IRegionManager _region = Indra.Injection.ServiceLocator.MefContainer.GetExportedValue<IRegionManager>();
    
                foreach (var v in _region.Regions["CrudCronogramaTarefas"].Views) _region.Regions["CrudCronogramaTarefas"].Remove(v);
    
                _region.Regions["CrudCronogramaTarefas"].RequestNavigate("/TarefaDefault", nr => { });
                var view = ((FrameworkElement)_region.Regions["CrudCronogramaTarefas"].ActiveViews.FirstOrDefault());
    
                ((UserControlCrudBase)view).Permissions = Sigep.WPF.Controls.UserControlCrudBase.PermissionsType.Update;
    
                view.DataContext = tarefa;
            }
        }
    
        public class PromotorIndex
        {
            public string Nome { get; set; }
            public int Index { get; set; }
        }
    
        // Converters
        public class DataInicioPercentagemConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var tarefa = (Tarefa)value;
                var candidatura = Indra.Injection.ServiceLocator.MefContainer.GetExportedValue<IDataManager>().Candidatura;
    
                double totalDias = candidatura.DataFim.Subtract(candidatura.DataInicio).Days;
                double diasTarefaInicio = tarefa.Inicio.Subtract(candidatura.DataInicio).Days;
    
                return new GridLength((diasTarefaInicio / totalDias * 100), GridUnitType.Star);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
        }
    
        public class DataMeioPercentagemConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var tarefa = (Tarefa)value;
                var candidatura = Indra.Injection.ServiceLocator.MefContainer.GetExportedValue<IDataManager>().Candidatura;
    
                double totalDias = candidatura.DataFim.Subtract(candidatura.DataInicio).Days;
                double diasTarefa = tarefa.Fim.Subtract(tarefa.Inicio).Days;
    
                return new GridLength((diasTarefa / totalDias * 100), GridUnitType.Star);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
        }
    
        public class DataFimPercentagemConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var tarefa = (Tarefa)value;
                var candidatura = Indra.Injection.ServiceLocator.MefContainer.GetExportedValue<IDataManager>().Candidatura;
    
                double totalDias = candidatura.DataFim.Subtract(candidatura.DataInicio).Days;
                double diasTarefaFim = candidatura.DataFim.Subtract(tarefa.Fim).Days;
    
                return new GridLength((diasTarefaFim / totalDias * 100), GridUnitType.Star);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
        }
    
        [ValueConversion(typeof(int), typeof(Brush))]
        public class IndexColorConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (targetType != typeof(Brush))
                    throw new InvalidOperationException("The target must be a Brush");
    
                switch((int)value)
                {
                    case 0:
                        return Brushes.Red;
                    case 1:
                        return Brushes.Green;
                    case 2:
                        return Brushes.Blue;
                    case 3:
                        return Brushes.Purple;
                    case 4:
                        return Brushes.Yellow;
                    case 5:
                        return Brushes.Brown;
                    default:
                        return Brushes.Pink;
                }
           }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (targetType != typeof(int))
                    throw new InvalidOperationException("The target must be a int");
    
                var color = (Brush)value;
    
                if (color == Brushes.Red) return 0;
                else if (color == Brushes.Green) return 1;
                else if (color == Brushes.Blue) return 2;
                else if (color == Brushes.Purple) return 3;
                else if (color == Brushes.Yellow) return 4;
                else if (color == Brushes.Brown) return 5;
                else return -1;
            }
        }
    }
    

    As you can see it has specific converters there, some objects we use to create some extra UX functionality and handles command interaction directly from the View.

    The Task (here called Tarefa from portuguese naming) itself is an Entity Framework Self Tracking Entity, and it is extended by adding a second partial class definition. The STE T4 template itself isn’t that much tweaked, most of the customization is done by adding extra partial class definition to objects we want to customize.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Sigep.Common.DataSelfTracking.Utils;
    
    namespace Sigep.Common.DataSelfTracking
    {
        [System.Diagnostics.DebuggerDisplay("{Codigo}")]
        public partial class Tarefa
        {
            private const double GRID_HEIGHT = 32;
    
            public Actividade ActividadeNum 
            {
                get 
                {
                    return Actividade;
                }
                set
                {
                    Actividade = value;
                    this.Numero = this.Actividade.Tarefas.Max(X=> X.Numero)+1;
                }
            }
    
    
            public Candidatura CandidaturaActual
            {
                get
                {
                    if (RelsRecursosInternosTarefas.Count > 0)
                        return this.RelsRecursosInternosTarefas[0].RecursoInterno.Estabelecimento.Promotor.Candidatura;
                    else if (RelsRecursosExternosTarefas.Count > 0)
                        return this.RelsRecursosExternosTarefas[0].RecursoExterno.EntidadeExterna.Promotores[0].Candidatura;
                    else
                        return null;
                }
            }
    
            public double TotalHoras
            {
                get
                {
                    return RelsRecursosInternosTarefas.Sum(r => r.Duracao) + RelsRecursosExternosTarefas.Sum(r => r.Duracao);
                }
            }
    
            public string Codigo
            {
                get
                {
                    return Actividade.PKID.ToString() + "." + Numero;
                }
            }
    
            public int DuracaoDias
            {
                get
                {
                    return (int)Math.Ceiling(DateTimeUtils.CalculateBusinessDays(Inicio, Fim));
                }
            }
    
            public IEnumerable<AlocacaoPromotorTarefa> PercentagensParticipacao
            {
                get
                {
                    var altura = GRID_HEIGHT / CandidaturaActual.Promotores.Count;
    
                    int index = 0;
                    foreach (var promotor in CandidaturaActual.Promotores.OrderBy(p => p.Nome))
                    {
                        var totalRI = RelsRecursosInternosTarefas.Where(r => r.RecursoInterno.Estabelecimento.Promotor == promotor).Sum(r => r.Duracao);
                        var totalRE = RelsRecursosExternosTarefas.Where(r => r.RecursoExterno.Estabelecimento.Promotor == promotor).Sum(r => r.Duracao);
    
                        yield return new AlocacaoPromotorTarefa() {
                            Actual = totalRI + totalRE,
                            Restante = TotalHoras - totalRI - totalRE,
                            Index = index++,
                            GridHeight = altura
                        };
                    }
                }
            }
    
            public DateTime GetPrimeiroDiaAno(int ano)
            {
                if (ano < Inicio.Year || ano > Fim.Year) throw new Exception("Ano Invalido");
                else if (Inicio.Year == ano) return Inicio;
                else return new DateTime(ano, 1, 1);
            }
    
            public DateTime GetUltimoDiaAno(int ano)
            {
                if (ano < Inicio.Year || ano > Fim.Year) throw new Exception("Ano Invalido");
                else if (Fim.Year == ano) return Fim;
                else return new DateTime(ano, 12, 31);
            }
    
            public int GetDuracaoDias(int ano)
            {
                if (ano < Inicio.Year || ano > Fim.Year) return 0;
                else if (ano == Inicio.Year && ano == Fim.Year) return (int)DateTimeUtils.CalculateBusinessDays(Inicio, Fim) + 1;
                else if (ano == Inicio.Year) return (int)DateTimeUtils.CalculateBusinessDays(Inicio, new DateTime(ano, 12, 31)) + 1;
                else if (ano == Fim.Year) return (int)DateTimeUtils.CalculateBusinessDays(new DateTime(ano, 1, 1), Fim) + 1;
                else return (int)DateTimeUtils.CalculateBusinessDays(new DateTime(ano, 1, 1), new DateTime(ano, 12, 31));
            }
    
            public double GetDuracaoMeses(int ano)
            {
                if (ano < Inicio.Year || ano > Fim.Year) return 0;
                else if (ano == Inicio.Year && ano == Fim.Year) return DateTimeUtils.CalculateMonths(Inicio, Fim);
                else if (ano == Inicio.Year) return DateTimeUtils.CalculateMonths(Inicio, new DateTime(ano, 12, 31));
                else if (ano == Fim.Year) return DateTimeUtils.CalculateMonths(new DateTime(ano, 1, 1), Fim);
                else return 12;
            }
        }
    
        public class AlocacaoPromotorTarefa
        {
            public double Actual { get; set; }
            public double Restante { get; set; }
            public int Index { get; set; }
            public double GridHeight { get; set; }
        }
    }
    

    As you can see, it’s mostly getters that return stuff that we want to bind to the View directly, that isn’t apart of the Model. This practice makes development very fast, as writing converters can be quite complex for some types of exposures.

    This is a lot of code, but hopefully will give you an idea of what to write on the ViewModel and what to write on the Model, how to extend the Model and how you bind stuff around.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm currently working in an application that has to navigate a webpage and recollect
I am currently working on an application that has different permissions/users for the local
I'm currently working on a large and old C++ application that has had many
I'm working on a PyGTK/glade application that currently has 16 windows/dialogs and is about
I'm currently working on a c# application that grabs a bunch of data from
I have recently started working on a legacy application that has most of its
Am currently working on an application that requires users to submit posts and comments
We are currently working on an application that will use a WCF service. The
I'm currently working on an application that allows people to schedule Shows for an
I am currently working on an application that allows reverse geocoding using silverlight +

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.