Mapping a List<long> in LINQ to SQL - Windows Phone 7.1

Asked

Viewed 146 times

2

Problem

I’m starting an application for Windows Phone 7.1, and I’m implementing the database, only I came across a situation that I couldn’t find any example of similar situation to try to solve, and I also couldn’t find anything that would help me in Microsoft documentation.

The situation is as follows:

I have a class similar to this:

public class Setup : INotifyPropertyChanged, INotifyPropertyChanging
{
    private long _id;
    private string _descricao;
    private IList<long> _tempos;

    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public virtual long Id
    {
        get { return _id; }
        set
        {
            if (value != _id)
            {
                _id = value;
                NotifyPropertyChanged("Id");
            }
        }
    }

    [Column]
    public virtual string Descricao
    {
        get { return _descricao; }
        set
        {
            if (value != _descricao)
            {
                _descricao = value;
                NotifyPropertyChanged("Nome");
            }
        }
    }

    // como eu faria para mapear corretamente esse campo
    [Column] 
    public virtual IList<long> Tempos
    {
        get
        {
            if (_tempos == null)
                _tempos = new List<long>();
            return _tempos;
        }
        set
        {
            if (value != _tempos)
            {
                NotifyPropertyChanging("");
                _tempos = value;
                NotifyPropertyChanged("Tempos");
            }
        }
    }

    // Version column aids update performance.
    [Column(IsVersion = true)]
    private Binary _version;

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangingEventHandler PropertyChanging;
    private void NotifyPropertyChanging(string propertyName)
    {
        if (PropertyChanging != null)
        {
            PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
        }
    }
}

Question

In case, how would I map correctly the field IList<long> Tempos , since it is not a simple field, it is a list of long, or would have to create a class (Time, for example) and treat as a 1 x N relationship? If so, how would it be? If possible with examples.

  • Like this Tempo would be filled?

  • With times in minutes that the setups were executed. It’s kind of a setup time history. I don’t know if it’s the best way.

2 answers

1

In case, how would I map correctly the field IList<long> Tempos , since it is not a simple field, it is a long list, or would have to create a class (Tempo, for example) and treat as a 1 x N relationship?

Exactly.

Any list or data structure suggesting cardinality N needs to be declared as another entity, related to the entity in question.

And how would I treat this cardinality? Which note would I use?

Sort of like this:

public class Entidade
{
    [Key]
    public int EntidadeId { get; set; }

    public virtual ICollection<Tempo> Tempos { get; set; }
}
  • And how would I treat this cardinality? Which note would I use?

  • I’ll put it in the answer.

  • No annotation is required about the property public virtual ICollection<Tempo> Tempos { get; set; }? The ORM (I don’t know which ORM it really is, I believe it is LINQ to SQL) will already understand this, if logically the class Tempo is properly mapped?

  • @Fernando Exactly. The Entity Framework is very smart.

  • But one question, is that I have some doubts about this ORM and I need to understand it a little better, to work with it. Then in class Tempo I have to create a reference to Setup in my case, or this relationship he already abstracts and maintains only the relationship in the database? I am asking this because it is a relationship 1 X N, then in the database N must have a reference to 1, which shall indicate which 1 N belongs to, and which Ns belong to 1. Was understandable?

  • Yes, you have to create the inverse property for Setup in Tempo, sort of like this: public virtual Setup Setup { get; set; }, and also the property that will represent the key: public int SetupId { get; set; }

  • Okay, Gypsy, I’m going to look at this approach in my project (the night), and see if it meets the needs (apparently, mentally compiled, hehe). And I’m sorry for the amount of questioning on the subject, it’s just that I was in a lot of doubt.

  • @Fernando Tranquilo. Anything screams, or calls me in chat.

Show 4 more comments

1


I was able to solve the problem (with the tips of @Ciganomorrisonmendez, but with some important modifications in relation to the collections), as follows:

I created a new entity to represent the times, called Tempo:

[Table]
public class Tempo : INotifyPropertyChanged, INotifyPropertyChanging
{
    private long _id;
    [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
    public virtual long Id
    {
        get { return _id; }
        set
        {
            if (value != _id)
            {
                NotifyPropertyChanging("Id");
                _id = value;
                NotifyPropertyChanged("Id");
            }
        }
    }

    private long _minutos;
    [Column]
    public virtual long Minutos
    {
        get { return _minutos; }
        set
        {
            if (value != _minutos)
            {
                NotifyPropertyChanging("Minutos");
                _minutos = value;
                NotifyPropertyChanged("Minutos");
            }
        }
    }

    [Column]
    public long SetupID;
    private EntityRef<Setup> _setup;
    [Association(Storage = "_setup", ThisKey = "SetupID")]
    public virtual Setup Setup
    {
        get { return _setup.Entity; }
        set
        {
            if (value != _setup.Entity)
            {
                NotifyPropertyChanging("Setup");
                _setup.Entity = value;
                NotifyPropertyChanged("Setup");
            }
        }
    }

    // ...
}

And modified the attribute mapping Tempos of class Setup, to the following:

[Table]
public class Setup : INotifyPropertyChanged, INotifyPropertyChanging
{        
    // ...

    private EntitySet<Tempo> _tempos;
    [Association(Storage = "_tempos", OtherKey = "Id")]
    public virtual EntitySet<Tempo> Tempos
    {
        get
        {
            if (_tempos == null)
                _tempos = new EntitySet<Tempo>();
            return _tempos;
        }
        set
        {
            if (value != Tempos)
            {
                NotifyPropertyChanging("Tempos");
                Tempos.Assign(value);
                NotifyPropertyChanged("Tempos");
            }
        }
    }

    // ...
}

The original problem was that the IList<long>, were not entities known by LINQ to SQL, then he didn’t know how to manage these attributes, in case the solution proposed by @Ciganomorrisonmendez, was to create an entity to represent the Tempo (In case the table that would save the times of the Setup), and represents it as a ICollection<Tempo> in the Setup, in the case of ICollection, also ended up not being recognized by the LINQ to SQL, who threw me the following Exception when trying to create the database: Unable to determine SQL type for 'System.Collections.Generic.ICollection'1, then researching I got to following "obscure" documentation from Microsoft, that saved my day. Where it explains and demonstrates how to represent/map relationships of cardinality in the LINQ to SQL where:

  • Entityset: Which is used as object/list to represent cardinality relations (1 X N and N X N);
  • Entityref: Which is used as an object to represent simple association between two entities;

Browser other questions tagged

You are not signed in. Login or sign up in order to post.