TypedView primary key

Posts   
 
    
Ian avatar
Ian
User
Posts: 511
Joined: 01-Apr-2005
# Posted on: 22-Apr-2005 18:17:05   

Hi,

Is it possible to specify a primary key on a typed view?

Cheers,

Ian.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 22-Apr-2005 18:53:43   

No. In 1.0.2004.2, which is almost there (final installer tests), you can add an entity mapped on a view and define a PK for that entity.

Frans Bouma | Lead developer LLBLGen Pro
RobertPhoenix avatar
Posts: 20
Joined: 14-Aug-2006
# Posted on: 16-Aug-2006 21:48:41   

I was trying to get a Primary Key on a typed view, did a search, and found this message.

So now I am wondering why this functionality doesn't exist.

Is it because I'm trying to do something that is not a good idea, or is it simply something that hasn't been asked for enough to find its way into the product?

I'm thinking of views as being read-only versions of entities - but maybe that is wrong as well rage

Can anyone straighten me out?

bclubb
User
Posts: 934
Joined: 12-Feb-2004
# Posted on: 17-Aug-2006 02:42:34   

Typed Views are read-only

To enable a primary key for a view you must map it in the software as an entity and there you can define the primary key.

RobertPhoenix avatar
Posts: 20
Joined: 14-Aug-2006
# Posted on: 17-Aug-2006 03:42:11   

Yes, that is what I am doing as a work around - Telling the designer to "Add an entity mapped on a view from the Catalog"

However, the resulting entity is not read only - at least not as far as I can see. It still has the save functions in it, and it is possible to write to the fields.

Since multiple people will be using the data layer, I would prefer if the DAL would not allow people to write code doing things they shouldn't do. I'd rather catch it at design/compile time rather than have an exception at run time.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 17-Aug-2006 07:44:15   

Here are your options:

1- Use a Typed View to use Data in a Read-Only way (You don't need a PK here).

2- Use an Entity to be able to define a PK (advantage: you can have relations with another entities)

3- Use option 2 and then set the Entity's fields to be read-only.

4- Use Option 2 then create a TypedList mapped onto this Entity's fields. (Gives you the read-only effect.)

If no option can work for you, then please explain your usage scenario, I mean what exactly do you want to have with a read-only view and a PK.

RobertPhoenix avatar
Posts: 20
Joined: 14-Aug-2006
# Posted on: 19-Aug-2006 02:31:28   

OK. So if I want a read-only object I can use a Typed view, and then need to set a filter for the 'Fill' method - assuming that I only want one record

So far so good.

However, it seems that the generated code does not type the rows, so I have to cast them. The real attraction of LLBLgen for me is the strong typing, so this is unexpected (especially when the row has been defined in the generated code).

Then I find I can set the value for a field and it compiles without problem i.e. it is not read only

            InvoiceInfoRow row = (InvoiceInfoRow) invoiceInfo.Rows[0];
            row.CurrencyId = 0;

Am I missing something, or am I using the class correctly, and this is just the way it is?

Thanks for any help.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 19-Aug-2006 18:20:55   

RobertPhoenix wrote:

OK. So if I want a read-only object I can use a Typed view, and then need to set a filter for the 'Fill' method - assuming that I only want one record

So far so good.

However, it seems that the generated code does not type the rows, so I have to cast them. The real attraction of LLBLgen for me is the strong typing, so this is unexpected (especially when the row has been defined in the generated code).

Then I find I can set the value for a field and it compiles without problem i.e. it is not read only

            InvoiceInfoRow row = (InvoiceInfoRow) invoiceInfo.Rows[0];
            row.CurrencyId = 0;

Am I missing something, or am I using the class correctly, and this is just the way it is? Thanks for any help.

You aren't missing anything, it's unfortunately how it works with datatables. The Rows collection is a member of the base class of the typedview: DataTable. This is a collection which has an indexer which returns 'object', so you always have to cast, no matter what type the DataRows have inside the collection.

Frans Bouma | Lead developer LLBLGen Pro
RobertPhoenix avatar
Posts: 20
Joined: 14-Aug-2006
# Posted on: 21-Aug-2006 19:38:22   

OK. So I understand that since you are inheriting from a dataTable the Rows are not going to be typed. So if I really wanted to have my Rows typed I would have to do something like this (which I could do everywhere by modifying a template. (But I realize this would add extra overhead, and many people would rather cast explicitly in their own code)



        public new List<InvoiceInfoRow> Rows
        {
            get
            {
                List<InvoiceInfoRow> typedRows = new List<InvoiceInfoRow>();
                foreach (DataRow row in base.Rows)
                {
                    typedRows.Add((InvoiceInfoRow)row);
                }
                return typedRows;
            }
        }

However, I do wonder why you added extra code to (for instance) TypedView.Template, not only to make the fields writeable, but also to add methods so they could be written, and then add a warning that it was not advisable to use them.

        public <[TypeOfTypedViewField]> <[TypedViewFieldName]> 
        {
            get 
            {
                if(Is<[TypedViewFieldName]>Null())
                {
                    // return default value for this type.
                    return (<[TypeOfTypedViewField]>)TypeDefaultValue.GetDefaultValue(typeof(<[TypeOfTypedViewField]>));
                }
                else
                {
                    return (<[TypeOfTypedViewField]>)this[_parent.<[TypedViewFieldName]>Column];
                }
            }
            set 
            {
                this[_parent.<[TypedViewFieldName]>Column] = value;
            }
        }

        /// <summary>
        /// Returns true if the TypedView field <[TypedViewFieldName]> is NULL, false otherwise.
        /// </summary>
        public bool Is<[TypedViewFieldName]>Null() 
        {
            return IsNull(_parent.<[TypedViewFieldName]>Column);
        }

        /// <summary>
        /// Sets the TypedView field <[TypedViewFieldName]> to NULL. Not recommended; a typed list should be used
        /// as a readonly object.
        /// </summary>
        public void Set<[TypedViewFieldName]>Null() 
        {
            this[_parent.<[TypedViewFieldName]>Column] = System.Convert.DBNull;
        }

I thought maybe the Set****Null method might be there because you needed it yourself, but VS can't find any references to it in the generated code.

Thanks for all the information you have given.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 22-Aug-2006 11:03:02   

The methods in the typed datarow are there if you want to use them: ((MyTypedViewRow)myTypedView[index]).SetFooNull();

Frans Bouma | Lead developer LLBLGen Pro